2

I have an AngularJS application with UI-Router. In my app.js file I have the following code (where AuthFact is a custom factory for authentication utility):

var testapp = angular.module('testapp', ['ui.router']);

testapp.config(function($stateProvider, $urlRouterProvider) {

   $urlRouterProvider.otherwise('/app/products');

   $stateProvider
    .state('app', {
        url: '/app',
        abstract: true,
        templateUrl: 'Views/App.html',
    })
    .state('app.products', {
        url: '/products',
        templateUrl: 'Views/Product/Product.html',
        controller: 'ProductController',
        authenticate: true
    })
    .state('login', {
    url: '/login',
    templateUrl: 'Views/Login.html',
    authenticate: false
    })
});

testapp.run(function ($rootScope, $state, AuthFact) {
$rootScope.$on("$stateChangeStart", 
   function (event, toState, toParams, fromState, fromParams) {
    if (!AuthFact.IsAuthenticated() && toState.authenticate == true) {
        $state.go('login');
        event.preventDefault();
    }
  });
});

When I run my application, it tries to go to the /products url because the otherwise route, but because the user isn't logged it redirect to the /login page.

The problem is that i have the following error:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: []

lin
  • 17,956
  • 4
  • 59
  • 83
Tom
  • 4,007
  • 24
  • 69
  • 105

2 Answers2

1

I've run into this problem too and here's how we fixed it...

First, the otherwise rule. You'll want to be directed to the right URL based on the authenticated state. To get the AuthFact in the config, you can use the function version of otherwise which is passed the $injector...

$urlRouterProvider.otherwise(function($injector) {
    var AuthFact = $injector.get('AuthFact');
    return AuthFact.IsAuthenticated() ? '/app/products' : '/login';
});

And then for your state change listener...

$rootScope.$on('$stateChangeStart', function(event, toState, toParams) {
    if (toState.authenticate && !AuthFact.IsAuthenticated()) {
        event.preventDefault();
        $state.go('login');
    }
});

Rather than adding top-level properties to your state configs (such as authenticate), you should probably use the data property, eg

data: {
    authenticate: true
}
Phil
  • 157,677
  • 23
  • 242
  • 245
0

This is caused by the fact, that if we go to Login ... we still do redirect. Adjust the listener like this

$rootScope.$on("$stateChangeStart", 
  function (event, toState, toParams, fromState, fromParams) {

    // if already redirected - GET OUT
    if(toState.name === "login"){
      return; // no redirect anymore.. 
    }

    // this condition could be true even if going to login...
    if (!AuthFact.IsAuthenticated() && toState.authenticate == true) {
        $state.go('login');
        event.preventDefault();
    }
});

Similar issue

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335