Directive to detect click out of an element?

Asked

Viewed 1,023 times

1

In Angularjs, we have the directive ngClick, which serves to perform an action when an element is clicked.

I’d like to create a directive, called ngClickout so that when the click occurs outside the element, perform an action.

How can I do that? I don’t have much "intimacy" yet with the angular.element (and I don’t want to wear jQuery).

  • What would be the purpose of this event? Can you give some practical example? For example, you want to fire the "click" on a input file by clicking on a div?

  • @Celsomtrindade for something similar to what I did in jQuery. I used to extend jQuery and create a function called clickOut, to reuse in any element I wanted: when clicking outside, perform an action. For example, I could change the value of a variable by clicking outside that "certain element"

1 answer

3


The simplest method of creating a directive that gets the result you are looking for, would be to use the element.bind('click'); that will detect the click on the element.

Just one detail before demonstrating the code, it is interesting that you do not use the prefix ng, by convention, to avoid conflict with other native Angular directives. Therefore, I recommend that you use your own prefix, such as wm.

Then see a basic example of a directive to detect the click:

.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, by clicking the button, you will call the directive event. I usually use this when I have some function common to the app whole, for example, the log out of a user. So instead of declaring a controller global just for that 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 the $scope.$digest() or $scope.$apply(), depending on whether the change is within the same directive or in 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: Answering the question of the comment

In case you want to propagate an event by clicking on body to remove an element from your screen, such as a modal, for example, I would recommend the use of events allied to $document so you can even detect the use of the key ESC, take the 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);
            });
        }
    }
});
  • I get the idea. But let’s assume that I wanted to make an element "disappear" by clicking on the "body" instead of clicking on the element itself. At the angle is there any way to detect this? Like this here

  • @Wallacemaxters updated my answer. Basically you need to "listen" to the document event instead of the specific element.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.