N.Zukowski
N.Zukowski

Reputation: 601

Angular ui router Maximum call stack size exceeded

recently I run into a problem with $stateChangeStart event, when I implemented the authentication in my app. I restricted access to some pages with boolean value like this:

.state('login', {
                url:'/login',
                templateUrl: 'modules/authentication/views/login.html',
                controller: 'LoginController',
                data: {
                    requireAuthentication: false
                }
            })

and I want to check, if there are any authentication data and if the user accesses a route with requireAuthentication: true he is automatically redirected to the login page. So, that is a standard authentication behaviour.

During the implementation I got Maximum call stack size exceeded error. I spent four night hours on finding what is wrong with those ~10 lines of code.

I will post an answer with my working solution for those, who will probably look after a working solution (as me). I think that is importaint for other members.

Upvotes: 0

Views: 891

Answers (1)

N.Zukowski
N.Zukowski

Reputation: 601

So, there is the working solution for me:

angular.module('YourModule', [...dependecies...])

    .run(function($rootScope, $cookies, $state) {
    $rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {
        var shouldLogin = toState.data.requireAuthentication !== undefined
            && toState.data.requireAuthentication;

        // NOT authenticated - wants any private stuff
        if(shouldLogin || fromState.name === "") {
            var token = $cookies.get('JWT') == null ? null : $cookies.get('JWT');
            if (token == null) {
                if(toState.name === 'login')
                    return;
                $state.go('login');
                event.preventDefault();
            } else {
                if(toState.name === toState.name)
                    return;
                //TODO: Check token
                $state.go(toState.name);
                event.preventDefault();
            }
        }
    });
});

So, I am getting my auth data from $cookies. If they are null I redirect to the login state.

The most importaint parts are:

fromState.name === "" This expression makes the event handler fire when you first open the page

if(toState.name === toState.name)
    return;

and

if(toState.name === 'login')
    return;

The both if expressions look really ill, but they do the trick. You won't get any stack size exceeded exceptions.

I tested the above code in Firefox, Chrome, Opera, Mozilla and Yandex browser, so I hope it will work for you.

Upvotes: 2

Related Questions