navaid icon indicating copy to clipboard operation
navaid copied to clipboard

Support for cancelling navigation?

Open germanftorres opened this issue 4 years ago • 2 comments

Hi, Is it possible to cancel navigation in navaid? In an editor scenario I would like to setup a dirty flag so that if the user wants to navigate off the page while the editor has changes, to prompt the user and give him the chance to cancel navigation.

In the svelte-demo repo I have seen a good example of route guards for the protected/admin area scenario. Following that sample code, I could conditionally prompt the user based on a dirty flag and do nothing at all if he or she chooses to cancel. But from navaids point of view, the navigation would have already happened and the history would reflect the new url.

I thinks a beforeNavigation hook would be a great addition to the the library.

Is it possible to solve this scenario in navaids current incarnation?

Thanks!!

const router = (
  Navaid('/')
  // support for cancelling navigation??
  .beforeNavigation((newPath, oldPath) => {
    if($dirtyFlag) {
      // prompt user  
      // return false to cancel navigation      
      return false;
    }
    return true;
  })
  .on('/', () => run(import('../routes/Home.svelte')))
  .on('/about', () => run(import('../routes/About.svelte')))
  .on('/login', () => run(import('../routes/Login.svelte')))
  .on('/private', () => onAdmin(import('../routes/Private.svelte')))
  .on('/forbidden', () => run(import('../routes/Forbidden.svelte')))
  .on('/blog', () => run(import('../routes/Blog.svelte')))
  .on('/blog/:postid', obj => run(import('../routes/Article.svelte'), obj))
  );
function onAdmin(thunk, obj) {
  if ($isAdmin) return run(thunk, obj);
  if ($isUser) return router.route('/forbidden', true);
  router.route('/login', true);
}

germanftorres avatar Jun 13 '20 19:06 germanftorres

I also vote for this. As I am trying a series of hacks and no one works... 😢

aldomendez avatar Jul 22 '20 16:07 aldomendez

The first router that did this was Ember's and it was bugged like crazy. It's in fact a very difficult problem, perhaps impossible to solve. When you click on the back button and select some very old history entry in the dropdown, a script can't really do much but accept that after the fact. Also the popstate event is not cancellable. Sometimes the history entries cross different websites too; so unless I'm wrong and forgetting some APIs, you can't cancel navigation, nor can you simulate it for end users by reverting the change because you can't fiddle with history in such a fine grained fashion (i.e, you can only push new entries at the top of the stack, not insert some back in the middle)

So, perhaps try to do that before routing occurs at all and handle it in an async fashion for when it already happened (popstate) via some bubble UI, etc.

PS: These "are you sure you want to navigate away" popups are very annoying anyway; a way better UX is to just remember the last draft :)

AlexGalays avatar Sep 12 '20 20:09 AlexGalays