I have an AngularJS application, that uses ui-router and ui-router-extras, where some transitions between states are intercepted and redirected to another ones.
So basically, when a $stateChangeStart
event is triggered, the app checks if that transition is allowed or needs to be blocked and then redirect the user somewhere else (eg: a login dialog, a missing step in the process, etc...). Transitions can be also cancelled.
The interception works this way:
$rootScope.$on("$stateChangeStart", function(e,to,toParams,from,fromParams){
if( <mustBeIntercepted> || <mustBeCancelled> ){
// this prevents the actual state change from happening
e.preventDefault();
if( <redirectionRequired> ){
$state.go( <stateName>, <stateParams>);
}
}
});
And this works nicely so far. The problem is that when cancelling a state change, $previousState
is not aware of the cancellation, and registers the current one as previous, in the same way that if you do not cancel the transition. So basically $previousState
is unaware of the transition cancellation. This causes that when trying to return to the previous state programmatically, it does not move because $state
== $previousState
.
I created a live demo here: http://plnkr.co/edit/dXjj2iSwDU1DtPMuqW1W?p=preview
Basically, you click on Step1, and then on Confirm, the app will cancel the transition and prompt you if you want to confirm. If you confirm, then it will transit to the originally desired state. Note that in the real app this is not done with confirm
but with a custom overlay that cannot block for an answer in the same way that confirm
does.
As you will notice, in the top bar there are two labels that show the content of $state
and $previousState
. If you cancel the confirm
prompt, you will see that $previousState
changes to "Step1" despite of that the transition didn't happen.
How can I avoid this?
The bug was reported and it has been resolved: https://github.com/christopherthielen/ui-router-extras/issues/120