1

In my angularjs app(using angular-ui), on refreshing the browser, the templates are being loaded of the particular state before the security context is being fetched from the server. $http call for getting the security context is being hit but since it is asynchronous, they are not set yet.

What is the best way to tackle this problem ?

And also, I have been trying to do the following :

//on the state change event from refresh

$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
    console.log("state change has started");
    if(fromState.name === '' && fromState.url === '^'){
        console.log("inside state change from refresh");
        //what needs to be done in this block to let the security context is fetched (should I use $timeout etc.) ?
           .........
           .........
    }
});
Vaibhav Pachauri
  • 2,671
  • 2
  • 19
  • 32
  • 1
    Just a note, I do use root state and its resolve, to load all the data for security.. drafted example could be found here http://stackoverflow.com/a/26241415/1679310 – Radim Köhler Mar 02 '15 at 10:13
  • Yes, I have tried that earlier but my application has grown a little too much in size and there is not a single 'root' state. I know it sounds little absurd but just can't apply this approach because if I have to inject the resolve object in the states I will have to do it at a lot of places. I guess it is the best approach but sadly I can't use it. Thanks a lot, much appreciated. Is there any other way? – Vaibhav Pachauri Mar 02 '15 at 10:30

2 Answers2

1

Do

event.preventDefault(); 

inside your if block. It will stop the state change. Then after security check, you may do

$state.go(toState, toParams);

But this is the wrong way. Like @Radim has suggested, you must use resolve.

Frozen Crayon
  • 5,172
  • 8
  • 36
  • 71
1

We use the following two Code snippets to tackle this issue. We tried a few other ways before we ended up here. This one seems to be quite robust...

In UserService Factory:

     // setup UserService OBject
    ...
    // bootstrap the Service 
    var tokenRetrieved = $location.search().token || localStorageService.get(AUTH_COOKIE_NAME);

    if (tokenRetrieved) {
                UserService.login(tokenRetrieved, true)
                    .then(function success(user) {
                        UserService.initialized = true;
                    }, function error(err) {
                        localStorageService.remove(AUTH_COOKIE_NAME);
                        UserService.initialized = true;
                    });
    } else {
          UserService.initialized = true;
    }

    return UserService;

And in $stateChangeStart Handler:

            if (UserService.initialized) {
                // here we check authorization for the toState
                ....


            } else {
                // if the UserService is not done initializing we cancel the stateChange and schedule it again in 200ms
                event.preventDefault();
                $rootScope.$log.log('preventing state change, because UserService not ready to check Authorization');
                $timeout(function () {
                    $state.go(toState, toParams);
                }, 200);
            }
Reto
  • 3,107
  • 1
  • 21
  • 33