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