4

Some actions in my Angular app require the user to be registered. If the user is not registered we want to show a "Register modal" and prevent the original action.

Those actions can be triggered via ng-click or any other "click binding" directive (for example the 'modal-toggle' one).

So I found this solution: https://stackoverflow.com/a/16211108/2719044

This is pretty cool but only works with ng-click.

I first wanted to make the "terminal" property of the directive dynamic but couldn't manage to do it.

So the idea was to set "terminal" to true and manually prevent default click action in the directive.

Here is my DOM

<!-- This can work with terminal:true and scope.$eval(attrs.ngClick) (see example above) -->
<div user-needed ng-click="myAction()">Do it !</div> 

<!-- This doesn't work. I can't manage to prevent the modal-toggle to be executed -->
<div user-needed modal-toggle="my-modal-id-yey">Show yourself modal !</div> 

And my directive(s) (which don't work...)

// First try (with terminal:true)
app.directive('userNeeded', function() {
    return {
        priority: -100,
        terminal: true,
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function(e) {
                if(isRegistered()) {
                    // Here we do the action like scope.$eval or something
                }
            });
        }
    };
});

// Second try (with stopPropagation)
app.directive('userNeeded', function() {
    return {
        priority: -100
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function(e) {
                if(!isRegistered()) {
                    e.stopPropagation();
                }
            });
        }
    };
});

...And that's why I'm here. Any idea ?

Thanks a lot.

Community
  • 1
  • 1
Maslow
  • 1,084
  • 9
  • 22
  • you should take a look at the angular-app project that handles authentification by the best way I found from now : https://github.com/angular-app/angular-app (see security module) – Jscti Apr 14 '14 at 18:42
  • This doesn't seem to resolve my problem. I don't need a general authentication feature. – Maslow Apr 15 '14 at 15:10
  • it's not. you can choose route by route if you want to restrict access (see `resolve` node when defining a new route) . And this restriction can be normal user / admin user.. But you don't have to adopt their pattern ;) it's just a very good example of what can be done. – Jscti Apr 15 '14 at 15:15
  • Another thing, the way you want to restrict your pages by "onclick" events can't be secure. It's not the links that you have to secure, it's the "route" – Jscti Apr 15 '14 at 15:16
  • All my actions are not routes. Sometimes it's just about showing or not a modal. And yes it can't be secure but in my case it's not important. The form in the modal is already secured, but the action of showing the modal doesn't need to be. I just want to catch the click and test via a directive if the user is authenticated. If not I don't show the modal and redirect to the login form. Don't know if I'm clear. – Maslow Apr 15 '14 at 16:24
  • sorry for the late reply, but i am facing similar issue (as in your title), i have solved the specific problem that you have using a custom ng-permission directive, which hides the element if user does not have permission for that action. – harishr Dec 19 '14 at 05:29
  • I am not sure I understand the question. Could you answers a few questions? My understanding is that you want
    to show if the user is not registered, and to show
    if the user IS registered, or vice versa. Is this true?
    – SoEzPz Jan 06 '15 at 17:57

1 Answers1

3

You were extremely close. Instead of stopPropagation you needed stopImmediatePropagation. The difference between the two is summarized in this StackOverflow answer by @Dave:

stopPropagation will prevent any parent handlers from being executed while stopImmediatePropagation will do the same but also prevent other handlers from executing.

So to fix the code, all we have to do is swap out that method and Voilà:

app.directive('userNeeded', function() {
    return {
        priority: -100
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function(e) {
                if(!isRegistered()) {
                    e.stopImmediatePropagation();
                }
            });
        }
    };
});

Here is an example Plunker of the working code. In the example I modified the directive slightly to allow specific events to be specified (such as user-needed="submit") by passing the value directly to the element.bind function; however, it defaults to 'click'.

Community
  • 1
  • 1
jgawrych
  • 3,322
  • 1
  • 28
  • 38