GomuGomuNoRocket
GomuGomuNoRocket

Reputation: 819

AngularJS UI routing $stateChangeStart dont work as expected

I have created an app with angular ui routing and states. Also I have a WEB API controller that can use to learn if user is authenticated or not. The problem is that http request to that WEB API has some delay to return result because is asynchronous.

I want, every time when user wants to go on state, to check if is authenticated or not, and give him access or redirect to login page. But first time when app running with someway i want to wait until i have answer from my WEB API.

I have this part of code

PlatformWeb.run(function ($rootScope, $state, $timeout, Authorization) {

$rootScope.$state = $state;

$rootScope.User = {
    isAuthenticated: null,
    targetState: null
}
Authorization.isAuthenticated().then(function (result) {
    $rootScope.User.isAuthenticated = result;

    $state.go($rootScope.User.targetState.name);
})
hasAccess = function () {
    return $rootScope.User.isAuthenticated;
}

$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
    $rootScope.User.targetState = toState;
    if ($rootScope.User.isAuthenticated == null)
        event.preventDefault();
    else {
        if (!hasAccess()) {
            event.preventDefault();
            $state.go('PlatformWeb.Login');
        }
    }
});});

The first time when app runs, $rootScope.User.isAuthenticated is null, so i will prevent to load state. Also with my 'Authorization' service i call my asynchronous function to get if user if authenticated or not. Before i prevent loading state i keep when user wants to go, so when i have my result back from WEP API, I change the state '$state.go($rootScope.User.targetState.name);' to the state he want. Then I know if is authenticated or not and i ask if has permissions to go. If he hasn't then i redirect him to login state.

BUT event.preventDefault(); doesn't work as expected. When i run my app i get this error 'angular.min.js:6 Uncaught Error: [$rootScope:infdig] http://errors.angularjs.org/1.3.7/$rootScope/infdig?p0=10&p1=%5B%5D' multiple times. Angular documentation says : '10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: []'

In my logic, 'stateChangeStart' function in condition '$rootScope.User.isAuthenticated == null' with event.preventDefault(); will make app logs here, and not run more until i know. When i get my result back from my WEBAPI I will go again in this function, but this time i know in which state to send him.

Upvotes: 1

Views: 473

Answers (1)

Radim Köhler
Radim Köhler

Reputation: 123861

I would suggest, firstly always check where is current change navigating to... and get out if it is already redirected

$rootScope.$on('$stateChangeStart', 
  function (event, toState, toParams, fromState, fromParams) {
    // are we already going to redirection target?
    if(toState.name === 'PlatformWeb.Login'){
      return; // yes, so do not execute the rest again...
    }
    $rootScope.User.targetState = toState;
    if ($rootScope.User.isAuthenticated == null)
        event.preventDefault();
    else {
        if (!hasAccess()) {
            event.preventDefault();
            // we will redirect here only if not already on that way...
            $state.go('PlatformWeb.Login');
            ...

Upvotes: 0

Related Questions