Oz Bar-Shalom
Oz Bar-Shalom

Reputation: 1855

Angular - ui-router wait for a promise before route

I am using Angular 1.5.8 and angular-ui-router 0.3.2. I need to resolve an authentication method on every route change.

I dont want to add the resolve property for each route so I created this in App.run

//check permissions

$rootScope.$on('$stateChangeStart', function (evt, toState) {
    if ($localStorage.token || toState.authenticated) {
        $http.defaults.headers.common = {
            'Authorization': 'Token ' + $localStorage.token,
            'Accept': 'application/json'
        };

        permissionAPI.me()
            .then(function(data){
                $rootScope.user = data;
            })
            .catch(function(){
                if(toState.authenticated) {
                    $rootScope.logout();
                }
            })
    }
    else {
        if(toState.authenticated) {
            $rootScope.logout();
        }
    }
});

`

It is usually working well, But I noticed that many times the application is routing before the promise permissionAPI.me() resolved and that causing errors later.

How can I make sure the route will take effect just after that promise?

Or, how can I make a main resolve for all of my routes by passing that promise from $stateChangeStart ?

Thank you!

Upvotes: 3

Views: 1633

Answers (1)

Andrew Osborn
Andrew Osborn

Reputation: 221

Create an app state! Abstract states are useful for if you need to access data consistently across your application, but don't want to have that data associated with a specific view.

    $stateProvider
        .state('app', { 
            url: '/app/',
            template: '<div ui-view></div>',
            controller: 'AppCtrl',
            abstract: true,
            resolve: {
                ActiveUser: function (AuthService) {
                    return AuthService.whoAmI();
                }
            }
        })
        .state('app.home', {
            url: '',
            templateUrl: 'app.home.html',
            controller: 'HomeCtrl',
            resolve: {
                Categories: function (ActiveUser, MessagesService) {
                    return MessagesService.getAll(User);
                }
            }
        });

You can then access that data in subsequent resolve blocks or in your controllers like app.controller('ExampleCtrl', function (ActiveUser) {}); as long as your controller is in a child state of 'app'. This is achieved with the naming convention 'app.'

Upvotes: 2

Related Questions