Policy to detect click outside an element?

1

In AngularJS, we have the directive ngClick , which is used to execute an action when an element is clicked.

I would like to create a directive, called ngClickout so that when the click occurs outside the element, it performs an action.

How can I do this? I do not have much "intimacy" yet with angular.element (and I do not want to use jQuery).

    
asked by anonymous 26.09.2016 / 15:49

1 answer

2

The simplest way to create a policy that gets the result you are looking for would be to use element.bind('click'); that will detect the click on the element.

Just one detail before demonstrating the code, it's interesting that you do not use the ng prefix, by convention, to prevent it from conflicting with other native Angular directives. So I recommend that you use your own prefix, such as wm .

So here is a basic example of a click detection policy:

.directive('wmClick', function() {
    return {
        restrict: 'A',
        link: function(scope, element) {
            element.bind('click', function(e) {
                //Execute sua função aqui
            });
        }
    }
});

<button wm-click type="button">Clique aqui</button>

With this, when you click the button, you will call the policy event. I usually use this when I have some function common to app all, such as log out of a user. So instead of declaring a global controller just for this purpose, I create a directive.

Now, if you need to propagate some change of values, as stated in the comments, you will need to use $scope.$digest() or $scope.$apply() , depending on whether the change is within the same directive or global scope. See the example:

.directive('wmClick', function($scope) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            element.bind('click', function(e) {
                //Execute sua função aqui

                $scope.meuNome = 'Novo Nome';
                $scope.$digest(); //Para aplicar a mudança dentro da própria diretiva
                $scope.$apply(); //Para aplicar a mudança fora da diretiva
            });
        }
    }
});

Edited : Replying to the comment question

In case you want to propagate an event by clicking on body to remove an element from your screen, as a modal, for example, I would recommend using events allied to $document so you can even detect the use of key ESC , see example:

.directive('wmClick', function($document, $scope) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            //Usado para clique diretamente no elemento
            element.bind('click', function(e) {
                //Execute sua função aqui

                $scope.meuNome = 'Novo Nome';
                $scope.$digest(); //Para aplicar a mudança dentro da própria diretiva
                $scope.$apply(); //Para aplicar a mudança fora da diretiva
            });

            //Usado para detectar clique no body ou tecla "ESC"
            var close = function() {
                scope.$apply(function() {
                    scope.valor = false;
                });
            };

            $document.on('click', close); //Detecta um clic no documento e chama a função

            $document.on('keyup', function(e) { //Detecta o uso da tecla "ESC" e chama a função
                if (e.keyCode === 27) {
                    close();
                }
            });

            scope.$on('$destroy', function() {
                $document.off('click', close);
                $document.off('keyup', close);
            });
        }
    }
});
    
26.09.2016 / 15:59