0

Basically what I'm trying to do is change the state depending on user authentication status.

When I do $state.go(); without $rootScope, I can redirect to the page without the error but when I do with

$rootScope.$on('$stateChangeStart', function (event) { $state.go(); event.preventDefault() })

Below Is the Controller Code:

DiaryDashboard.controller('AppController', 
  ['$scope', '$rootScope', '$localStorage', '$http', '$state'
  , function ($scope, $rootScope, $localStorage, $http, $state) {

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

    if ($localStorage.userdetails &&
        $localStorage.userdetails.isAuthenticated == true) {

        //Check for Authentication state
        //If not redirect to the state in the else clause
        //Populate the $rootScope with user details
        $rootScope.userdetails = $localStorage.userdetails;

        //Switch to the parent state
        $state.go();
        event.preventDefault();

    } else {

        //If User not authenticated
        //GO to the Authentication State
        $state.go('auth');
        event.preventDefault();

    }
  })

}]);
5
  • the error is because of your code is causing infinite loop, when you call $state.go() it calls $stateChangeStart & this cycle going on Commented May 2, 2015 at 12:01
  • Can you plz help me on how to solve the problem? Commented May 2, 2015 at 12:03
  • could you tell me why $state.go(); is required when user is authenticated..why you want to get back to parent state event if he is authenticated Commented May 2, 2015 at 12:06
  • I remove that but again the $state.go('auth') in the else block is giving the error Commented May 2, 2015 at 12:16
  • take a look at mine answer Commented May 2, 2015 at 12:24

5 Answers 5

4

The most important thing here is to understand this:

Do not redirect if not needed. Other words, if user is already redirected to intended state - we should leave... There is a working plunker with similar solution.

Check this Q & A:

Angularjs ui-router. How to redirect to login page

the adjusted code:

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

    var isNavigatingToAuth = toState.name === "Auth";

    if(isNavigatingToAuth){

       return; // no need to redirect 
    }

    if ($localStorage.userdetails &&
        $localStorage.userdetails.isAuthenticated == true)
    ...
Sign up to request clarification or add additional context in comments.

Comments

0

You are creating a redirection loop. You need to check whether the new route is already the route where you want to send your client to.

$rootScope.$on("$routeChangeStart", function (event, next, current) {
    if (next == 'my-auth-page') {
        // already going to auth page no redirect needed
    } else {
        // not going to auth page, we should redirect now
        $location.path('my-auth-page');
    } 
});

Comments

0

You are basically creating a state change interceptor.

The thing is, on every one of your branches in '$stateChangeStart' you have a $state.go . Since this is an interceptor, every time you invoke $state.go , the handler for $stateChangeStart will be invoked, and this is why you get this invocation loop that ends with that error.

You need to write the handler in a way that has at least one branch that does not invoke $state.go

Here is how we implemented it:

//The list of states that do not need authentication (like auth)
var authorizedStates = ['auth', 'someOtherAuthorizesState', 'etc'];

// This method reports if a state is one of the authorizes states
var isChildOfAuthorizedStated = function (stateName) {
  var isChild = false;
  authorizedStates.forEach(function (state) {
    if (stateName.indexOf(state) === 0) {
      isChild = true;
    }
  });
  return isChild;
};

$rootScope.$on('$stateChangeStart',
  // The stateChangeStart handler
  function (event, toState, toParams, fromState, fromParams) {
    // Check if the future state is not an authorized state 
    // and if the user is not authenticated. 
    if (!isChildOfAuthorizedStated(toState.name) && !Auth.isAuthenticated()) {
      event.preventDefault();
      $state.go('auth');
    }
);

1 Comment

It still reports Maximum range exceeded
0

Your code is going in infinite as you are doing $state.go in both cases, You could should not do $state redirection user is authorized & second condition is proper which is in else block

   if ((!$localStorage.userdetails || !$localStorage.userdetails.isAuthenticated) 
           && toState.name != 'auth') { //<--this condition will stop infinite loop
        //If User not authenticated
        //GO to the Authentication State
        $state.go('auth');
        event.preventDefault();
    }

Update

Other thing which I wanted to point out about your code is $stateChangeStart should be inside a run block(which initialize exactly after config block) so that It would be common for all state & will initialized this condition at the starting of your app

Code

app.run(function($rootScope){
    $rootScope.$on('$stateChangeStart', function (event, toState) {

        if ($localStorage.userdetails && $localStorage.userdetails.isAuthenticated == true) {
              if ((!$localStorage.userdetails || !$localStorage.userdetails.isAuthenticated) 
               && toState.name != 'auth') { //<--this condition will stop infinite loop
            //If User not authenticated
            //GO to the Authentication State
            $state.go('auth');
            event.preventDefault();
        }
    })
});

Also do use service to store UserDetails using $rootScope in AngulaJs is considered as bad code practice.

2 Comments

yes i know i did it in hasty to store in rootScope.. Let me Apply your corrections
@ChanX take you time & let me know..Glad to help you..Thanks :)
0

Use $state.go("main", {}, {notify:false}); for not notify to "$stateChangeStart"event and not allow the event loop.

$state.go("main", {}, {notify:false});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.