frictionlesspulley
frictionlesspulley

Reputation: 12368

handling interaction between angular directives for authentication

I have two directives, for the sake of simplicity I have reduced my problem to the following:

Directive 01 : handles authentication

it is responsible for opening modals / windows and getting user authenticated.

angular
.module('app.directives')
.directive('requiresLogin', function(){       
     return {
         restrict : 'A',
         link : function() { //..}
     }
})

Directive 02 : performs specific action

angular
.module('app.directives')
.directive('like', function(){

     return {
         restrict : 'A',
         link : function() { //..}
     }
})

Both directive 01 and 02 bind click events.

I am bit confused about the design of two directives.

I could make the second directive a child of the first one and get communication between the directive, which to some extent makes sense as the single responsibility of each directive is maintained under this pattern. However all my future directives that would need authentication will be children of the first directive.

My Question is :

How can prevent the second directive (actual action) based on the result of first "authenticating" directive ? Is there any other way of doing this without making a "parent-child" relation between them ?

Upvotes: 1

Views: 225

Answers (2)

benek
benek

Reputation: 2178

You can use "require" definitly well explained in the following post :

How to require a controller in an angularjs directive

In your context you could do:

.directive('requirelogin', function() {
    return {
        scope: true,
        controller: function() {
            var isLogged = false;

            this.isLogged = function() {
                if(isLogged) return isLogged; 
                alert("You are not logged!");
            };

            this.login = function(){
                isLogged = true;            
            };
        }
    };
})

.directive('like', function() {
    return {
        scope: true,
        require: '^requirelogin',
        link: function(scope, element, attrs, loginCtrl) {
            scope.loginCtrl = loginCtrl;
            scope.sayILike = function(){
                if(scope.loginCtrl.isLogged()){
                    alert('I like');
                }
            };

            scope.login = function(){
                scope.loginCtrl.login();
            };
        }
    };
});

Working : http://jsfiddle.net/bennekrouf/nq9g33Lt/25/

Upvotes: 2

coma
coma

Reputation: 16649

Only add the "action" directive and inject an auth service to it:

http://jsfiddle.net/coma/dby686ab/

Logic

app.factory('user', function() {

    var roles = ['user'];

    return {
        hasRole: function(role) {

            return !role || roles.indexOf(role) > -1;
        }
    };
});

app.directive('like', function(user) {

    return {
        restrict: 'A',
        link    : function(scope, element, attrs) {

            element.on('click', function () {

                if (user.hasRole(attrs.authRole)) {

                    element.addClass('liked');
                    element.off('click');

                } else {

                    alert('Unauthorized.');
                }
            });
        }
    };
});

View

<a like="">Dogs</a>
<a like="" auth-role="user">Birds</a>
<a like="" auth-role="admin">Whales</a>

Upvotes: 0

Related Questions