Haga clic fuera de div – cuando div tiene botones que disparan eventos – angularjs

Estoy usando la siguiente directiva para detectar cuándo se hace un clic fuera de un div:

app.directive('clickOut', function ($window, $parse) { return { restrict: 'A', link: function (scope, element, attrs) { var clickOutHandler = $parse(attrs.clickOut); angular.element($window).on('click', function (event) { if (element[0].contains(event.target)) return; clickOutHandler(scope, {$event: event}); scope.$apply(); }); } }; }); 

En este div:

  

Funciona bien, cuando hace clic fuera de la div, se activa la función closeMyPopup (), el problema es que la div tiene botones que activan otras funciones. Por alguna razón, cuando se llama a otra función, (como cuando se hace clic en los botones), el clic fuera del evento se activa llamando al closeMyPopup (), los botones están dentro del div, por lo que no se debe llamar el clic del evento fuera. ¿Hay otra directiva que pueda usar, que tenga el comportamiento correcto y no active el clic afuera cuando dispare otra función? ¿O cómo puedo solucionar esto?

También uso esta otra directiva, con el mismo problema:

 app.directive("outsideClick", ['$document', '$parse', function ($document, $parse) { return { link: function ($scope, $element, $attributes) { var scopeExpression = $attributes.outsideClick, onDocumentClick = function (event) { var isChild = $element.find(event.target).length > 0; if (!isChild) { $scope.$apply(scopeExpression); } }; $document.on("click", onDocumentClick); $element.on('$destroy', function () { $document.off("click", onDocumentClick); }); } } }]); 

Es porque el evento se está propagando al objeto Window .

 - Window - document - dialog - button 

En la jerarquía anterior, si ocurre un evento de clic en el último elemento del button , el evento se propagará al elemento principal hasta que llegue a la ventana y luego cerrará el cuadro de diálogo.

Solución 1:

Detenga la propagación del evento en cada función del controlador pasando el evento como un parámetro y llamando a la función event.stopPropagation() :

  

 $scope.onCancelAnnouncement($event) { $event.stopPropagation(); } 

Solución 2:

Deje que el evento se propague y verifique el elemento de destino:

 angular.element($window).on('click', function (event) { var target = $(event.target); if(target.attr("id") === "anyid") { // or target.hasClass("someclass") // or target.closest(".some-selector") // just ignore } else { // Do whatever you need } }); 

Exactamente: los eventos se presentarán a cada objeto en la jerarquía DOM anidada a menos y hasta que detenga su propagación. Esto, por supuesto, es por diseño: JavaScript no asume que “el hombre más íntimo que puedo encontrar que está escuchando este evento” es el único que podría estar interesado en él. Todos los que dicen que lo están escuchando, que están en posición de escucharlo, lo escucharán, cada uno a su vez … a menos que uno de ellos reprima explícitamente la propagación posterior, a la que JS dejará de buscar a alguien más para enviar. a (Nadie tiene que “enviar el evento al contenedor externo”. En cambio, solo tienen que decirle a JS que no lo envíe).