I'm attempting to send the user to a specific 'closed' UI State in Angular using the following:
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
// check the destination is active
if(toState.data.isClosed) { // note that the 'closed' state has isClosed set to false
event.preventDefault();
$state.go('closed');
}
$rootScope.data = toState.data; // getting executed twice after our state transition to 'closed'
$log.debug(toState);
});
The issue I'm having is that $rootScope.data = toState.data
is getting called twice AFTER we've transitioned to the 'closed' state.
On the first time $startChangeStart
executes when navigating to our 'order' state with data.isClosed = true
set in the router, the state is changed to 'closed' and the code in question doesn't get executed.
As we are changing states to 'closed' now, $startChangeStart
gets triggered again, and the code in question executes for the first time with toState being our 'closed' state.
Strangely, the code is then subsequently executed, starting after the if() logic with toState being the original state of 'order'... meaning that when everything is loaded up, the $rootScope.data variable contains the data from 'order' rather than 'closed'. Adding a few breakpoints and the debugging code above confirms.
Any explanations?
Update
Due to the execution pattern with the state transition to the 'closed' state, I've added a return to ensure that the continued execution after the $state.go()
call is terminated. Revised code:
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
// check the destination is active
if(toState.data.isClosed) { // note that the 'closed' state has isClosed set to false
event.preventDefault();
$state.go('closed');
return;
}
$rootScope.data = toState.data; // getting executed twice after our state transition to 'closed'
$log.debug(toState);
});
This is now working as expected, but I'm not sure it's 'correct'.
The solution with return statement is simple correct. I created this playground, where you can test that.
Let's have these states. Firstly some state with isClosed false - which should not be managed by our event listener
and these will be caught and redirected
Now, whenever we go to any state, the event
$stateChangeStart
is fired. So if we go to "not handled" states (state1, state2) - the event will be triggered once.If we go to handled states (stateClosed1, stateClosed2), event is fired always twice:
Just to be sure: the event is really fired twice. And that's why we should write these listeners rather like this (get out ASAP):
In fact, this solution (getting out as soon as possible), was issue in these Q & A: