Edit: The proposed approach of using resolve
isn't working for me. The $stateChangeStart
event seems to be happening before the resolve stuff. Plunker.
I'm using $on($stateChangeStart)
to do authentication for routes. The way I was doing it, there was a problem: if an user was trying to access a state he's unauthorized to see, the state would be shown briefly before my code redirected him.
To get around this, the best way seems to be to use event.preventDefault()
+ $state.go(toState.name, {}, { notify: false })
, but { notify: false }
has a known bug.
I'm not sure what a good way of handling this situation is. The only idea I've got is to toggle the display
property of body
, but I don't like that solution.
- The "flickering"
display: none
->display: block
onbody
. - It's expensive to hide and redisplay such a large portion of the DOM (or is it?).
How should this situation be handled?
angular
.module('app', ['ui.router'])
.config(config)
.run(run)
;
function config($locationProvider, $urlRouterProvider, $stateProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
template: '<p>home</p>'
})
.state('one', {
url: '/one',
template: '<p>one</p>',
authenticate: true
})
.state('two', {
url: '/two',
template: '<p>two</p>'
})
;
}
function run($rootScope, $state, $timeout) {
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState) {
if (toState.authenticate) {
// event.preventDefault();
angular.element(document.body).css('display', 'none');
if (isAuthenticated(false)) {
// $state.go(toState.name, {}, { notify: false });
angular.element(document.body).css('display', 'block');
}
else {
$timeout(function() {
$state.go('two');
angular.element(document.body).css('display', 'block');
}, 2000);
}
}
});
}
function isAuthenticated(hardcode) {
return hardcode;
}
<!DOCTYPE html>
<html ng-app='app'>
<head>
<script data-require="angular.js@1.4.6" data-semver="1.4.6" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.min.js"></script>
<script data-require="ui-router@0.2.11" data-semver="0.2.11" src="https://rawgit.com/angular-ui/ui-router/0.2.11/release/angular-ui-router.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<base href='/'>
</head>
<body>
<ul>
<li><a ui-sref='home'>home</a></li>
<li><a ui-sref='one'>state one</a></li>
<li><a ui-sref='two'>state two</a></li>
</ul>
<div ui-view></div>
</body>
</html>