Reputation: 19218
Code:
angular
.module('mean-starter')
.run(run)
;
function run($rootScope, Auth, $state) {
function preventStateChange (message, event, redirect) {
console.log(event);
event.preventDefault();
alert(message);
if (redirect) {
$state.go(redirect);
}
}
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
if (typeof toState.authenticate === 'undefined') { // this route doesn't require permissions
return;
}
event.preventDefault(); // WORKS HERE
Auth
.getCurrentUser()
.then(function (currentUser) {
event.preventDefault(); // DOESN'T WORK HERE
var isLoggedIn = !!currentUser._id;
var isAdmin = isLoggedIn && currentUser.role === 'admin';
var isAuthorized = isLoggedIn && currentUser._id.toString() === toParams.id;
if (toState.authenticate.loggedOut && isLoggedIn) { // this route requires you to be logged out
preventStateChange("You're logged in.", event);
}
else if (!isLoggedIn) {
preventStateChange('Must be logged in to access this route.', event, 'login');
}
else if (toState.authenticate.authorized && !isAuthorized && !isAdmin) {
preventStateChange('You are not authorized to access that route.', event);
}
else if (toState.authenticate.isAdmin && !isAdmin) {
debugger;
event.preventDefault();
preventStateChange('You must be an admin to access this route.', event);
}
})
;
});
}
When I'm logged in as a non-admin and I go to localhost:3000/admin
:
Why is this?
When I inspect in the debugger, event.preventDefault
is defined, and it seems to get called. This is the event
object that gets logged out to the console:
It's defaultPrevented
property gets set to true
!
UPDATE: It works outside of the .then
, but it does NOT work inside of the .then
. Which is surprising because it is defined inside of the .then
.
UPDATE 2: My guess is that the event
does it's default action BEFORE it reaches the .then
. And so essentially, .then
is too late.
Upvotes: 1
Views: 1934
Reputation: 113906
Your second guess is essentially correct. The browser actions are resolved after all the current event handlers have returned. In fact, one of the mechanisms to prevent default action (the original mechanism actually) was to have the event handler return false
or 0
to cancel default action. So it happens semi-synchronously - it happens inside an asynchronous function but is resolved at the end of the current event loop.
The only way around it is to call .preventDefault()
before calling your promise.
Upvotes: 1