pro.mean pro.mean - 4 months ago 15
AngularJS Question

resolve property of .state does not work as expected

I want to use

ui-router
resolve property to simply check just before entering that state whether user is logged in or not by using
AuthService
function but it gives no result.


  • angular v 1.5.8

  • angular-ui.router v 0.2.18



index.route.js



angular.module('app').config(routerConfig);

/** @ngInject */
function routerConfig($stateProvider, $urlRouterProvider, USER_ROLES) {
$stateProvider
.state('dashboard', {
url: "/dashboard",
templateUrl: "app/views/dashboard_2.html",
data: { requiresAuth: true, pageTitle: 'Dashboard', authorizedRoles: ['admin'] } ,
resolve: {
isLoggedin: ['AuthService', function(AuthService) {
return AuthService.isAuthenticated();
}]
}
})
});


auth.service.js



'use strict';
angular
.module('app')
.factory('AuthService', function($log, $http, $q, $cookies){
var authService = {};
// .. login and logout methods...
authService.isAuthenticated = function () {
return !!$cookies.getObject('currentUser');
};

return authService;
});


index.run.js



angular
.module('app')
.run(function($rootScope, $state, $log, AuthService, AUTH_EVENTS) {
$rootScope.$on('$stateChangeStart', function (event, to, toParams, from, fromParams) {
// $log.debug('state change starts');
$log.debug(to.resolve);

});


I read that resolve return promise object , but I have simple function whcih return true/false

is that the problem? Kindly suggest me what to do in proper way so that

Answer

Since the resolve function expects a promise, you should return a promise. Modify your code like:

isLoggedin: ['AuthService', '$q', function(AuthService, $q) {
    var defer = $q.defer();
    var isLoggedIn = AuthService.isAuthenticated();

    if (isLoggedIn) {
       defer.resolve();
    } else {
       defer.reject();
    }

    return defer.promise;
}]

Alternatively, you can remove the resolve keyword from your state configuration and modify your run block like this:

angular
        .module('app')
        .run(function ($rootScope, $state, $log, AuthService, AUTH_EVENTS) {
            $rootScope.$on('$stateChangeStart', function (event, toState, toParams, from, fromParams) {
                if (toState.name === 'dashboard') {
                    if (!AuthService.isAuthenticated()) {
                        // Do not allow navigation to state
                        e.preventDefault();
                        // Redirect to somewhere else like login page
                        //$state.go('login')
                        return;
                    }
                }
            });
        });

Edit

You can modify the above (2nd approach) code to make it generic like this:

angular
        .module('app')
        .run(function ($rootScope, $state, $log, AuthService, AUTH_EVENTS) {
            $rootScope.$on('$stateChangeStart', function (event, toState, toParams, from, fromParams) {
                if (toState.requireAuthenticationFoo && !AuthService.isAuthenticated()) {
                    // Do not allow navigation to state
                    e.preventDefault();
                    // Redirect to somewhere else like login page
                    //$state.go('login')
                    return;
                }
            });
        });

Now use the key requireAuthenticationFoo in your state configuration:

state('dashboard', {
    url: "/dashboard",
    templateUrl: "app/views/dashboard_2.html",
    data: {requiresAuth: true, pageTitle: 'Dashboard', authorizedRoles: ['admin']},
    requireAuthenticationFoo: true
})