Reputation: 465
I want to create an angularjs directive for restricted actions of my web site. For example I have an anchor which would trigger a route change in angular, but before that I want to show a modal login dialog.
I can stop the routing with preventDefault
, but I can't resume the routing. I have also tried with dummy event triggering (element.triggerHandler('click')
) without success.
I'd like to apply the directive not only to route changing but any other action.
.directive('loginRequired', ['AuthService', 'AUTH_EVENTS',
function(AuthService, AUTH_EVENTS) {
return {
link : function(scope, element, attrs) {
element.on('click', function(e) {
if (!AuthService.isAuthenticated()) {
e.preventDefault();
$('#myModal').modal();
scope.$on(AUTH_EVENTS.loginSuccess, function() {
//resume event
});
console.log('$scope.$on happened');
}
});
}
}
}]);
Any suggestion?
Upvotes: 1
Views: 4499
Reputation: 465
The solution I found is:
.value('lastPrevented', {
elem : null
}).directive('loginRequired', ['AuthService', 'lastPrevented',
function(AuthService, lastPrevented) {
return {
link : function(scope, element, attrs) {
element.on('click', function(e) {
if (!AuthService.isAuthenticated()) {
lastPrevented.elem = element;
e.preventDefault();
$('#myModalLogin').modal();
}
});
}
}
}]).run(['lastPrevented', '$rootScope', 'AUTH_EVENTS', '$timeout',
function(lastPrevented, $rootScope, AUTH_EVENTS, $timeout) {
$rootScope.$on(AUTH_EVENTS.loginSuccess, function() {
$timeout(function() {
if (!!lastPrevented.elem) {
lastPrevented.elem[0].click();
lastPrevented.elem = null;
}
})
});
}]);
That's not resuming... which literally I think is not feasible. The solution is inspired by this question.
Upvotes: 1
Reputation: 1323
I don't think Event.preventDefault()
will capture or delay events. AFAIK, it only cancels them outright (see MDN). I don't believe there's a way of resuming the original event with its handler(s) in tact. (But perhaps you don't intend the term 'resume' to be taken quite so literally.)
In this specific case, I think you'll have to examine $(e.target).attr('href')
, and later** use it to update the route (you'll need to inject the $location
service (Docs) and use its .path()
getter/setter method).
-- Best of luck!
**Quick note: you're most likely going to want to pass your 'resume' handlers to your AuthService.isAuthenticated()
method, as a callback, as it may wait on some kind of asynchronous business. Rough example:
element.on('click', function(e) {
e.preventDefault();
newRoute = $(e.target).attr('href');
AuthService.isAuthenticated(function () {
$('#myModal').modal();
scope.$on(AUTH_EVENTS.loginSuccess, function() {
$location.path(getWhatYouNeedFromUrlString(newRoute));
});
}));
});
You'd setup your .isAuthenticated()
method to fire the callback when the user is indeed authenticated.
Upvotes: 0