AngularJS ng-click StopPropagation

J'ai un événement de clic sur une rangée de table et dans cette rangée il y a aussi un bouton de suppression avec un événement de clic. Lorsque je clique sur le bouton Supprimer, cliquez sur Événement sur la ligne.

Voici mon code.

<tbody> <tr ng-repeat="user in users" class="repeat-animation" ng-click="showUser(user, $index)"> <td>{{user.firstname}}</td> <td>{{user.lastname}}</td> <td>{{user.email}}</td> <td><button class="btn red btn-sm" ng-click="deleteUser(user.id, $index)">Delete</button></td> </tr> </tbody> 

Comment puis-je empêcher que l'événement showUser soit déclenché lorsque je clique sur le bouton Supprimer dans la cellule du tableau?

La directive ngClick (ainsi que toutes les autres directives d'événement) crée $event variable qui est disponible sur la même portée. Cette variable est une référence à l'objet d' event JS et peut être utilisée pour appeler stopPropagation() :

 <table> <tr ng-repeat="user in users" ng-click="showUser(user)"> <td>{{user.firstname}}</td> <td>{{user.lastname}}</td> <td> <button class="btn" ng-click="deleteUser(user.id, $index); $event.stopPropagation();"> Delete </button> </td> </tr> </table> 

PLUNKER

Un ajout à la réponse de Stewie. Dans le cas où votre rappel décide si la propagation doit être interrompue ou non, j'ai trouvé utile de passer l'objet $event sur le rappel:

 <div ng-click="parentHandler($event)"> <div ng-click="childHandler($event)"> </div> </div> 

Et puis, dans le rappel lui-même, vous pouvez décider si la propagation de l'événement doit être arrêtée:

 $scope.childHandler = function ($event) { if (wanna_stop_it()) { $event.stopPropagation(); } ... }; 

J'ai écrit une directive qui vous permet de limiter les zones où un clic a eu effet. Il pourrait être utilisé pour certains scénarios comme celui-ci, donc, au lieu d'avoir à faire face au cas par cas, vous pouvez simplement dire que "les clics ne sortiront pas de cet élément".

Vous l'utiliseriez comme suit:

 <table> <tr ng-repeat="user in users" ng-click="showUser(user)"> <td>{{user.firstname}}</td> <td>{{user.lastname}}</td> <td isolate-click> <button class="btn" ng-click="deleteUser(user.id, $index);"> Delete </button> </td> </tr> </table> 

Gardez à l'esprit que cela empêcherait tous les clics sur la dernière cellule, pas seulement sur le bouton. Si ce n'est pas ce que vous voulez, vous voudrez peut-être envelopper le bouton comme ceci:

 <span isolate-click> <button class="btn" ng-click="deleteUser(user.id, $index);"> Delete </button> </span> 

Voici le code de la directive:

 angular.module('awesome', []).directive('isolateClick', function() { return { link: function(scope, elem) { elem.on('click', function(e){ e.stopPropagation(); }); } }; }); 

Dans le cas où vous utilisez une directive comme moi, c'est la façon dont cela fonctionne lorsque vous avez besoin de la liaison de deux voies de données, par exemple après la mise à jour d'un attribut dans n'importe quel modèle ou collection:

 angular.module('yourApp').directive('setSurveyInEditionMode', setSurveyInEditionMode) function setSurveyInEditionMode() { return { restrict: 'A', link: function(scope, element, $attributes) { element.on('click', function(event){ event.stopPropagation(); // In order to work with stopPropagation and two data way binding // if you don't use scope.$apply in my case the model is not updated in the view when I click on the element that has my directive scope.$apply(function () { scope.mySurvey.inEditionMode = true; console.log('inside the directive') }); }); } } } 

Maintenant, vous pouvez facilement l'utiliser dans n'importe quel bouton, lien, div, etc., de la manière suivante:

 <button set-survey-in-edition-mode >Edit survey</button> 
 <ul class="col col-double clearfix"> <li class="col__item" ng-repeat="location in searchLocations"> <label> <input type="checkbox" ng-click="onLocationSelectionClicked($event)" checklist-model="selectedAuctions.locations" checklist-value="location.code" checklist-change="auctionSelectionChanged()" id="{{location.code}}"> {{location.displayName}} </label> $scope.onLocationSelectionClicked = function($event) { if($scope.limitSelectionCountTo && $scope.selectedAuctions.locations.length == $scope.limitSelectionCountTo) { $event.currentTarget.checked=false; } };