提问人:michael_knight 提问时间:11/30/2013 最后编辑:Mosh Feumichael_knight 更新时间:4/2/2019 访问量:291547
AngularJS ng-click stopPropagation
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
答:
840赞
Stewie
11/30/2013
#1
ngClick 指令(以及所有其他事件指令)创建在同一作用域上可用的变量。此变量是对 JS 对象的引用,可用于调用:$event
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>
评论
2赞
user1338062
2/21/2014
我无法弄清楚这在控制器代码中是否可用 - $scope.$event 似乎不起作用。有什么想法吗?
93赞
Stewie
2/21/2014
@event对象是在 ng-click 指令中创建的,您可以将其传递给您的处理程序函数:。ng-click
ng-click="deleteUser(user.id, $event)"
6赞
user1338062
2/21/2014
谢谢,有点想通了,但我认为它仍然很臭:)
2赞
djheru
5/8/2015
我认为像这样执行多个表达式是一种反模式。为什么不将 $event 作为第三个参数传递给 deleteUser(),然后在该函数中停止传播()呢?
20赞
Desty
10/22/2015
我也必须添加,否则单击按钮时,呼叫会将我重定向到应用程序的根目录。$event.preventDefault()
$event.stopPropagation()
136赞
korya
1/7/2015
#2
这是对Stewie答案的补充。如果您的回调决定是否应该停止传播,我发现将对象传递给回调很有用:$event
<div ng-click="parentHandler($event)">
<div ng-click="childHandler($event)">
</div>
</div>
然后在回调本身中,你可以决定是否应该停止事件的传播:
$scope.childHandler = function ($event) {
if (wanna_stop_it()) {
$event.stopPropagation();
}
...
};
评论
11赞
Eason
5/9/2015
这比在 HTML 属性中执行多个表达式更优雅,谢谢
3赞
ThinkBonobo
9/30/2015
请记住将“$event”参数放在 html ng-click 指令中。起初我偶然发现了这一点。
1赞
Edgar Chavolla
3/31/2016
要立即停止,最好使用 $event.stopImmediatePropagation()
0赞
tfrascaroli
7/14/2016
如此简单,却如此被忽视。我看着选择的答案,心想“真的吗?这么丑?甚至没有意识到将其作为参数传递。真的很好。
-14赞
Hems
7/16/2015
#3
<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;
}
};
评论
7赞
paisanco
7/16/2015
你能解释一下为什么你认为这回答了这个问题吗?
0赞
hewstone
11/22/2016
它有点回答了这个问题。它显示了如何将事件传递给回调,这比最初的问题所确定的要多。
11赞
Jens
1/12/2016
#4
我写了一个指令,让你限制点击生效的区域。它可以用于像这样的某些场景,因此不必根据具体情况处理点击,您可以直接说“点击不会来自这个元素”。
你可以这样使用它:
<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();
});
}
};
});
评论
0赞
maaartinus
5/6/2016
好!我已将您的指令重命名为 ,因为我实际上从不想传播已经处理的事件。ngClick
1赞
Jens
5/7/2016
要小心。其他一些插件可能实际上想听这些点击。如果使用在外部单击时关闭的工具提示,则它们可能永远不会关闭,因为外部单击不会传播到正文。
0赞
maaartinus
5/7/2016
这是一个很好的观点,但这个问题也会发生在你的指令中。也许我应该为事件添加一个属性并处理它......不知何故。理想情况下,在原始指令中,但修改它听起来很脏。ignoreNgClick=true
ngClick
0赞
Jens
5/7/2016
是的,确实如此,这就是为什么除非我真的需要它,否则我不会使用此指令。有一次,由于这个原因,我什至不得不发出另一个指令来继续点击传播。所以我有一个隔离点击指令,然后几个父母我有另一个继续点击指令。这样,仅跳过中间元素的点击。
1赞
Heriberto Magaña
4/30/2017
#5
如果您使用的是像我这样的指令,那么当您需要双数据方式绑定时,例如,在任何模型或集合中更新属性后,这就是它的工作方式:
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>
评论