Luka
Luka

Reputation: 4211

Angular ui-router infinite loop when urlRouteProvider.otherwise is set

I'm getting an infinite loop for this code:

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
        var isLoggedIn = (authService.authentication && authService.authentication.isAuth);
        if (isLoggedIn) {
            //if user is logged and tries to access login page, prevent it
            if (toState.name === 'app.login') {
                event.preventDefault();
                return fromState;
            } 
        } else {
            if (toState.name !== 'app.login') {
                event.preventDefault();
                $state.go('app.login');
                return;
            }
        }
    });

I also have this set:

function config($stateProvider, $urlRouterProvider, $ocLazyLoadProvider) {
    $urlRouterProvider.otherwise('/main');

    $stateProvider
    .state('app', {
        abstract: true,
        url: '',
        controller: 'mainCtrl',
        controllerAs: 'mainCtrl',
        template:'<div ui-view></div>'      
    })
    .state('app.login', {
        url: '/logn'
        controller: 'loginCtrl',
        controllerAs: 'loginCtrl',
        templateUrl: 'app/security/login.html'
    })
    .state('app.main', {
        url: '/main'
        controller: 'mainCtrl',
        controllerAs: 'mainCtrl',
        templateUrl: 'app/main.html'
    })
    ...
}

Now i'm getting infinite digest loop when user enters the site and must be authenticated. It goes like this:

  1. User enters the address ie: http://localhost
  2. The default route (otherwise) fires and reddirects user to http://localhost/#/main
  3. $OnStateChangeStart fires (for app.main) and test if user is logged in, if not then prevent default event end redirect to 'app.login';
  4. $OnstateChangeStart fires (for app.login) and test if toState.name is app.login' if so, then no need to redirect so return.
  5. I don't know why but then $OnStateChangeStart fires again but for app.main. end it lops over and over.

Please help.

Upvotes: 2

Views: 4459

Answers (1)

Will.Harris
Will.Harris

Reputation: 4014

Change the otherwise() method declaration to a state name transition instead of a URL transition which you are currently using. This solved it for me when I experienced this problem.

Heres an example:

$urlRouterProvider.otherwise(function($injector, $location){
  $injector.invoke(['$state', function($state) {
    $state.go('app.main');
  }]);
}); 

An alternate way of getting the $state and executing the $state.go would be

var $state = $injector.get('$state');
$state.go('app.main');

I'm not very experienced in Angular so I don't know why this solves it so if anybody can elaborate please do!

Update

The accepted answer in this SO post seems to provide a good explanation on why this happens.

Upvotes: 12

Related Questions