Qual é a melhor maneira de cancelar a propagação de events entre as chamadas ng-click aninhadas?

Aqui está um exemplo. Digamos que eu queira ter uma superposição de imagem como muitos sites. Então, quando você clica em uma miniatura, uma sobreposição preta aparece sobre a janela inteira e uma versão maior da imagem é centralizada nela. Clicar na sobreposição preta a dispensa; Clicar na imagem chamará uma function que mostre a próxima imagem.

O html:

O javascript:

 function OverlayCtrl($scope) { $scope.hideOverlay = function() { // Some code to hdie the overlay } $scope.nextImage = function() { // Some code to find and display the next image } } 

O problema é que, com essa configuração, se você clicar na imagem, nextImage() e hideOverlay() serão chamados. Mas o que eu quero é que somente nextImage() seja chamado.

Eu sei que você pode capturar e cancelar o evento na function nextImage() assim:

 if (window.event) { window.event.stopPropagation(); } 

… Mas eu quero saber se há uma maneira melhor de fazer isso que não requer que eu prefixe todas as funções dos elementos dentro da sobreposição com este trecho.

O que @JosephSilber disse, ou passe o object $ event para o ng-click callback e pare a propagação dentro dele:

 
 $scope.nextImage = function($event) { $event.stopPropagation(); // Some code to find and display the next image } 

Use $event.stopPropagation() :

 

Aqui está uma demonstração: http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p=preview

Eu gosto da idéia de usar uma diretiva para isso:

 .directive('stopEvent', function () { return { restrict: 'A', link: function (scope, element, attr) { element.bind('click', function (e) { e.stopPropagation(); }); } }; }); 

Então use a diretiva como:

 

Se você quisesse, poderia tornar essa solução mais genérica como essa resposta para uma pergunta diferente: https://stackoverflow.com/a/14547223/347216

Às vezes, pode fazer mais sentido apenas fazer isso:

  

Eu escolhi fazer isso dessa maneira porque eu não queria que myClickHandler() interrompesse a propagação do evento nos muitos outros locais em que ele foi usado.

Claro, eu poderia ter adicionado um parâmetro booleano à function de manipulador, mas stopPropagation() é muito mais significativo do que apenas true .

Isso funciona para mim:

 Action this.doSomething = function($event) { $event.stopPropagation(); $event.preventDefault(); }; 

Se você não quiser adicionar a propagação de parada a todos os links, isso também funciona. Um pouco mais escalável.

 $scope.hideOverlay( $event ){ // only hide the overlay if we click on the actual div if( $event.target.className.indexOf('overlay') ) // hide overlay logic } 

Se você inserir ng-click = “$ event.stopPropagation” no elemento pai de seu modelo, a stopPropogation será capturada quando ela aparecer na tree, portanto, você só precisará escrevê-la uma vez para o modelo inteiro.

Você pode registrar outra diretiva em cima do ng-click que altera o comportamento padrão do ng-click e interrompe a propagação do evento. Dessa forma, você não precisaria adicionar $event.stopPropagation manualmente.

 app.directive('ngClick', function() { return { restrict: 'A', compile: function($element, attr) { return function(scope, element, attr) { element.on('click', function(event) { event.stopPropagation(); }); }; } } }); 

Uso do controlador IN

$ scope.methodName = function (event) {event.stopPropagation ();}