Skip to content
This repository has been archived by the owner on Sep 20, 2020. It is now read-only.

$previousState unaware of prevented state transition during $stateChangeStart #120

Closed
vtortola opened this issue Dec 12, 2014 · 2 comments
Closed
Assignees
Labels
Milestone

Comments

@vtortola
Copy link

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.

@christopherthielen
Copy link
Owner

Confirmed, thank you for the bug report. This is due to relying on ui-router's event system, which is sub-par. The event system doesn't provide any feedback for when the transition has been cancelled.

I think the issue your use case highlights could be fixed by hooking into the (somewhat untested and mostly undocumented) ui-router-extras 0.0.10 $transitionStart event. This event is fired in response to $stateChangeStart and exposes the transition promise for the current transition. The promise should be properly rejected when the transition is cancelled (via evt.preventDefault(), or via a superseding transition) and we can manage the $previousState code in a more readable manner.

@christopherthielen christopherthielen added this to the 0.0.12 milestone Jan 27, 2015
@christopherthielen christopherthielen self-assigned this Jan 27, 2015
@vtortola
Copy link
Author

vtortola commented Feb 1, 2015

Nice. Thanks.

impatient pushed a commit to impatient/ui-router-extras that referenced this issue Feb 5, 2015
 - This allows previous state to properly manage transition cancelled and redirected

 Closes christopherthielen#120
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants