I have a state that requires authorization. I listen to the $stateChangeStart
event and if the toState.data.protected
and the user is not authorized I call e.preventDefault()
and $state.go('login')
.
When I open the app in root url I'm automatically redirected to protected state. This causes 10 $digest loops and I end up in the login state when I open the app in the root url and I'm automatically redirected to a protected state.
Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
See this plnkr: http://plnkr.co/edit/1voh7m?p=preview
I successfully use similar code in different project with angular 1.2.26 with no errors.
Example code angular 1.4.1, ui.router 0.2.15
:
//config block
$urlRouterProvider.otherwise('/main');
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'main.html',
controller: 'MainController as main',
data: {'protected': true}
})
.state('login', {
url: '/login',
templateUrl: 'login.html',
controller: 'LoginController as login'
});
// in a run block
$rootScope.$on("$stateChangeStart", function (event, toState) {
if (!event.defaultPrevented && toState.data &&
toState.data.protected) {
// the user is not authorized, do not switch to state
event.preventDefault();
// go to login page
$state.go('login');
}
});
Do you know what causes the loop?
I wonder if the things might be happening like this:
$urlRouter.update()
and starts transition to main.submainEDIT: Simplified state configuration.
This is an issue of the UI.Router – see this issue on Github: https://github.com/angular-ui/ui-router/issues/600
Basically, if you use .otherwise('/main')
(also pointed out by @Grundy) then the url is changed to /main
when the path cannot be resolved. After $locationChangeSuccess
my listener is called and I reject the redirection using event.preventDefault()
. This causes the location to change back to the unknown path thus causing the fallback path to be used again. This causes the infinite loop. The solution is this:
$urlRouterProvider.otherwise(function($injector) {
var $state = $injector.get('$state');
$state.go('main');
});
You can state a function which gets called with $injector
and you can redirect to your main state (or 404) without back-and-forth location changes. Thx to the guys on Github, I should have searched there before posting this question.
Working plunk: http://plnkr.co/edit/eQXaIk
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With