1

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.

Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
GomuGomuNoRocket
  • 771
  • 2
  • 11
  • 37

1 Answers1

0

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');
            ...
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • yeah, this is good idea. but the problem is that event.preventDefault(); doesnt work as expected, and not make app 'waits'. – GomuGomuNoRocket Sep 05 '16 at 08:22
  • Could you create some plunker? I am ready to assist? Check this for working example http://stackoverflow.com/a/26800804/1679310 and some more resources... – Radim Köhler Sep 05 '16 at 08:25
  • Also here .. http://stackoverflow.com/a/26135437/1679310. prevent default is there to stop standard JS behavior, not the flow of your code. You should use return to get out, if the toState is what you wanted to redirect to.. – Radim Köhler Sep 05 '16 at 08:27