AngularJS ng-click stopPropagation

У меня есть событие "Событие" в строке таблицы, и в этой строке есть кнопка "Удалить" с кликом "Событие" . Когда я нажимаю кнопку "Удалить", также запускается событие "Событие" в строке.

Вот мой код.

<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>

Как я могу предотвратить запуск события showUser при нажатии кнопки удаления в ячейке таблицы?

Ответ 1

Директива

ngClick (как и все другие директивы событий) создает переменную $event, доступную в той же области. Эта переменная является ссылкой на объект JS event и может использоваться для вызова 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

Ответ 2

В дополнение к ответу Стьюи. Если ваш обратный вызов решает, следует ли остановить распространение или нет, мне было полезно передать объект $event в обратный вызов:

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

И затем в самом обратном вызове вы можете решить, следует ли останавливать распространение события:

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

Ответ 3

Я написал директиву, которая позволяет вам ограничить области, где действует клик. Он может использоваться для определенных сценариев, подобных этому, поэтому вместо того, чтобы иметь дело с щелчком по каждому случаю, вы можете просто сказать, что "клики не выйдут из этого элемента".

Вы бы использовали его следующим образом:

<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>

Имейте в виду, что это предотвратит все клики по последней ячейке, а не только кнопку. Если это не то, что вы хотите, вы можете обернуть эту кнопку следующим образом:

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

Вот код директивы:

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

Ответ 4

В случае, если вы используете такую ​​директиву, как я, так это то, как это работает, когда вам требуется привязка к двум каналам данных, например, после обновления атрибута в любой модели или коллекции:

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')
        });
      });
    }
  }
}

Теперь вы можете легко использовать его в любой кнопке, ссылке, div и т.д. так:

<button set-survey-in-edition-mode >Edit survey</button>

Ответ 5

<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;
      }
   };