question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Not possible to add state.resolve from $stateChangeStart event

See original GitHub issue

Overview: Sometimes it’s desirable to add state resolves on the fly, instead of needing to add them to all states beforehand. For example, a resolve that verifies a user is authenticated or fetches the user from an API.

It’s possible to do this with $routeChangeSuccess using the following code:

// @see http://stackoverflow.com/a/18245378/1738217
function authenticate() {
    if ( user.isAuthenticated ) {
        return;
    }
    // simulate deferred
    return $timeout(function() {
        user.isAuthenticated = true;
    }, 3000);
}

$rootScope.$on( "$routeChangeStart", function( e, next ) {
    next.resolve = angular.extend( next.resolve || {}, {
        __authenticating__: authenticate
    });
});

However the same is not possible with $stateChangeSuccess. This is because the event is broadcast with to.self, see this line. This means if you add a resolve in the $stateChangeSuccess event, you are actually adding on to.self.resolve which is never considered for resolve.

_Related:_ https://github.com/angular-ui/ui-router/issues/1153

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:35 (12 by maintainers)

github_iconTop GitHub Comments

2reactions
stephengardnercommented, Jan 15, 2017

Adding my route authentication as an example, Thanks again for the clarification @christopherthielen This might help someone who was in my position.

/**
 * Authentication Resolvable - if I add  "authenticate" to a route params, this will make sure the user is logged in
 * before proceeding.  
 */
$transitions.onStart({}, (trans) => { // on any route, do the following...
  let next = trans.to(); // get the state and its params
  if (next.authenticate) {
    trans.addResolvable({
      token : 'authResolve', // the token can be anything, here, we never actually use it in this specific case
      deps : ['$state', 'Auth', '$q'], // inject what I need
      resolveFn: ($state, Auth, $q) => {
        return new $q((resolve, reject) => { // make sure this is a promise, in order to delay the route
          let onUserLoggedIn = () => {
            console.log('[Auth Service] the necessary *authenticate* state PASSED the resolvable, continue on!');
            return resolve();
          };
          let onUserLoggedOut = () => {
            console.log('[Auth Service] the necessary *authenticate* state FAILED the resolvable, going to login page!');
            $state.go('login');
            return reject();
          };
          // this can be substituted for any promise, observable, or async operation, here I'm using an observable
          Auth.isLoggedInAsync$().subscribe((isLoggedIn) => {
            if(!isLoggedIn) return onUserLoggedOut();
            return onUserLoggedIn();
          })
        })
      }
    }); }
});
1reaction
christopherthielencommented, Jan 12, 2017

@stephengardner in the past, you HAD to use the Resolvable constructor, but that’s not good API for end users:

import { Resolvable } from "angular-ui-router";

...
transition.addResolvable(new Resolvable('foo', ...));

In rc.1 I remembered to allow addResolvable to take a ResolvableLiteral which is a plain object, as shown above. 👍

I’ll add an example to the docs. https://github.com/ui-router/core/commit/6d41c318c4a87bab32a56362a3d0e81b707bb2b5

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Defer a StateChangeStart event until after a ui-router ...
My problem is that the stateChangeStart event is triggering prior to the app resolve such that the listener stops the state change (via...
Read more >
Guide: UI-Router 1.0 Migration
In UI-Router legacy (versions 0.x), you may have used the $stateChangeStart / $stateChangeSuccess events and resolve to handle concerns like ...
Read more >
Angular UI-Router: An Elegant & Maintainable Way to Prevent ...
Learn easy solutions for preventing state change with UI-Router from one of our ... listening to the $stateChangeStart event on rootScope.
Read more >
AngularJS UI Router: Understanding "Resolve" - YouTube
What is " Resolve " attribute- Resolving vs. not Resolving -What are " Resolved Results" (or data)-What is execution workflow of UI Router...
Read more >
How to prevent a tab state change with $stateChangeStart
on('$stateChangeStart', function (event, toState, toParams, ... It is still not working with beta 8: http://codepen.io/dbarr/pen/CHgmE
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found