I am working on creating a new application using the Kendo SPA framework. One must-have feature is the ability to cancel navigation to a route, for example - don't allow the user to navigate away if the current has unsaved changes.
According to the documentation, this should be as simple as calling e.preventDefault() in the router's change event. And this does work in the simplest scenario - if you wire up the change event and call preventDefault, the route will be cancelled, you stay on the current view, and the url is reverted back to it's original value.
However, I feel that is overly simplistic. In reality, you would never simply just cancel the route. You need to make a call to see if there are unsaved changes so that you can determine whether or not the navigation is allowed. And this is where my problem lies.
In my scenario, I have a callback that is executed in the router change event that checks to see if the navigation is allowed. If I hit a route that I cannot leave, then I call e.preventDefault and the view does not change (which is good), but the route does not revert back to the original value (which is bad). So now the wrong url is showing in the browser. What's worse is that if I now attempt to navigate to a different route, this will cause an infinite loop where the change event keeps firing and being cancelled, which locks up the browser.
I have created an example in JS Bin that demonstrates this behavior - http://jsbin.com/EXARiTiJ/10. Here are the steps to recreate the issue:
According to the documentation, this should be as simple as calling e.preventDefault() in the router's change event. And this does work in the simplest scenario - if you wire up the change event and call preventDefault, the route will be cancelled, you stay on the current view, and the url is reverted back to it's original value.
However, I feel that is overly simplistic. In reality, you would never simply just cancel the route. You need to make a call to see if there are unsaved changes so that you can determine whether or not the navigation is allowed. And this is where my problem lies.
In my scenario, I have a callback that is executed in the router change event that checks to see if the navigation is allowed. If I hit a route that I cannot leave, then I call e.preventDefault and the view does not change (which is good), but the route does not revert back to the original value (which is bad). So now the wrong url is showing in the browser. What's worse is that if I now attempt to navigate to a different route, this will cause an infinite loop where the change event keeps firing and being cancelled, which locks up the browser.
I have created an example in JS Bin that demonstrates this behavior - http://jsbin.com/EXARiTiJ/10. Here are the steps to recreate the issue:
- When the page loads, it will first navigate to the Home view
- Click on "Orders" to navigate to the Orders view. This will navigate correctly and update the url appropriately.
- Click "Products" to navigate to the Products view. Again, this will navigate correctly and update the url.
- Click "Orders" to navigate back to the Orders view. The code in the change event will call preventDefault and this will trigger the error condition. The Products view will remain visible, but the url now shows "/orders" - however, it should still show "/products".
- Now click "Home" to try to navigate to the Home view. Be warned though, this will now create an infinite loop and lock up the browser.
It seems like this is a bug with the router, but maybe I am missing something. Is there a different way that I should be handling canceling the route navigation? If this is a bug, I would like to know if there is a workaround/fix that can be implemented, since this feature is a must-have for my application.