urlRouterProvider.otherwise conflicting with $stateChangeStart

661 Views Asked by At

I don't have a root / state. My root state is

$urlRouterProvider.otherwise('/dashboard');

and in $stateChangeStart if user is not logged in i redirect to login

$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
    var requireLogin = toState.data && toState.data.access!=undefined;
    if (requireLogin && !Auth.isLoggedIn() {
        $rootScope.redirectState =  toState.name;//Auto redirect to the state
        event.preventDefault();
        $state.go('login');
        return;
    }
});

This works fine if I directly hit /dashboard but if i hit / it gets redirected to /dashboard which internally get redirected to /login till which is fine, but after that it gets redirected to /dashboard and /login again and again.

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.3.15/$rootScope/infdig?p0=10&p1=%5B%5D
    at REGEX_STRING_REGEXP (angular.js:63)
    at Scope.$get.Scope.$digest (angular.js:14346)
    at Scope.$get.Scope.$apply (angular.js:14571)
    at bootstrapApply (angular.js:1455)
    at Object.invoke (angular.js:4203)
    at doBootstrap (angular.js:1453)
    at bootstrap (angular.js:1473)
    at angularInit (angular.js:1367)
    at HTMLDocument.<anonymous> (angular.js:26304)
    at jQuery.Callbacks.fire (jquery.js:3099)

Any idea on how to solve this?

2

There are 2 best solutions below

2
On

In case that we need to

  • go to login if not authenticated
  • go to dashboard if authenticated

we can updated this event handler:

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

  var isGoingToLogin = toState.name === "login";

  if (isGoingToLogin && Auth.isLoggedIn)
  {
      event.preventDefault(); 
      $state.go('dashboard');  

      return;
  }

  if (isGoingToLogin || Auth.isLoggedIn)
  {
      return;
  }

  var requireLogin = toState.data && toState.data.access !== undefined;

  if (requireLogin) {

    $rootScope.redirectState = toState.name; //Auto redirect to the state

    event.preventDefault(); 
    $state.go('login');

    return;
  }
});

And again use two approaches:

I. State 'dashboard' is public. Check it in this working plunker

.state('dashboard', {
    url: "/dashboard",
    templateUrl: 'tpl.html',
    data: {
        //access: true
    },
})

II. Or redirect to 'login' - the other solution plunker

//$urlRouterProvider.otherwise('/dashboard');
$urlRouterProvider.otherwise('/login');
2
On

Solution here is to use one of these. I created plunkers for both, based on this Q & A: How can I fix 'Maximum call stack size exceeded' AngularJS

I. State 'dashboard' is public. Check it in this working plunker

.state('dashboard', {
    url: "/dashboard",
    templateUrl: 'tpl.html',
    data: {
        //access: true
    },
})

II. Or redirect to 'login' - the other solution plunker

//$urlRouterProvider.otherwise('/dashboard');
$urlRouterProvider.otherwise('/login');

The point is, the otherwise should be really free of any limitations. It should be some public page ... if there is any... or directly the login. That's the point