AngularJS ng-click 停止传播

IT技术 javascript angularjs angularjs-ng-click
2021-01-27 03:07:02

我在表格行上有一个点击事件,在这一行中还有一个带有点击事件的删除按钮。当我单击删除按钮时,该行上的单击事件也会被触发。

这是我的代码。

<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当我单击表格单元格中的删除按钮时,如何防止触发事件?

5个回答

ngClick 指令(以及所有其他事件指令)创建$event在同一范围内可用的变量。此变量是对 JSevent对象的引用,可用于调用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

我也必须添加$event.preventDefault(),否则$event.stopPropagation()在单击按钮时调用会将我重定向到我的应用程序的根目录。
2021-03-12 03:07:02
@event对象的NG-点击指令内建立,它是提供给你把它传递给你的ng-click处理函数:ng-click="deleteUser(user.id, $event)"
2021-03-16 03:07:02
谢谢,有点想通了,但我认为它仍然很臭:)
2021-03-26 03:07:02
我认为像这样执行多个表达式是一种反模式。为什么不直接将 $event 作为第三个参数传递给 deleteUser() 然后在该函数中 stopPropagation() 呢?
2021-04-07 03:07:02
我不知道这在控制器代码中是否可用 - $scope.$event 似乎不起作用。有任何想法吗?
2021-04-08 03:07:02

Stewie 的回答的补充。如果您的回调决定是否停止传播,我发现将$event对象传递给回调很有用

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

然后在回调本身中,您可以决定是否应该停止事件的传播:

$scope.childHandler = function ($event) {
  if (wanna_stop_it()) {
    $event.stopPropagation();
  }
  ...
};
这比在 html 属性中执行多个表达式更优雅,谢谢
2021-03-22 03:07:02
请记住将 '$event' 参数放在 html ng-click 指令中。起初我偶然发现了这一点。
2021-03-31 03:07:02
如此简单,却又如此被忽视。我看着选择的答案,想“真的吗?这么丑吗?”。甚至没有意识到将它作为参数传递。非常好。
2021-04-05 03:07:02
对于立即停止更好地使用 $event.stopImmediatePropagation()
2021-04-09 03:07:02

我写了一个指令,可以让你限制点击有效的区域。它可以用于像这样的某些场景,因此不必逐案处理点击,您只需说“点击不会来自此元素”。

你会像这样使用它:

<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();
            });
        }
   };
});
这是一个很好的观点,但是这个问题也会发生在您的指令中。也许我应该ignoreNgClick=true为事件添加一个类似的属性并处理它......不知何故。理想情况下,在原始ngClick指令中,但修改它听起来很脏。
2021-03-23 03:07:02
小心点。其他一些插件可能实际上想要收听这些点击。如果您使用在外部单击时关闭的工具提示,它们可能永远不会关闭,因为外部单击不会传播到主体。
2021-04-08 03:07:02
是的,这就是为什么除非我真的需要它,否则我不会使用这个指令。由于这个原因,我什至不得不制定另一个指令来继续点击传播。所以我有一个隔离点击指令,然后一对父母我有另一个继续点击指令。这样,只跳过中间元素的点击。
2021-04-08 03:07:02
好的!我已将您的指令重命名为ngClick,因为我实际上从不想传播已处理的事件。
2021-04-11 03:07:02

如果您使用像我这样的指令,这就是当您需要两种数据方式绑定时的工作方式,例如在更新任何模型或集合中的属性后:

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

你会解释为什么你认为这回答了这个问题吗?
2021-03-28 03:07:02
它有点回答这个问题。它显示了如何将事件传递给回调,这比最初的问题更重要。
2021-04-02 03:07:02