在 Angular 中,当复选框有更改事件时,如何停止 TR 单击事件的传播()?

wor*_*joe 5 click event-handling angular

我正在使用 Angular 6。我有一个<TR>带有点击事件的表格行 ( )。出于测试目的,我们只说事件打印“嘎嘎!” 到控制台。这是 HTML:

<tr *ngFor="let t of things" (click)="quack()">
  ...
</tr>
Run Code Online (Sandbox Code Playgroud)

在组件中:

quack() {
  console.log('quack!');
}
Run Code Online (Sandbox Code Playgroud)

现在,在这一行中,我有一个复选框。这是一个 Bootstrap 4 自定义复选框,但我认为这不是我需要解决的问题的重要内容。该复选框有一个自定义指令,它添加了一个更改事件处理程序(不是点击事件)。HTML 的简化版本是:

<tr *ngFor="let t of things" (click)="quack()">
  ...
  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" id="cb{{t.id}}" name="cb{{t.id}}" 
     [my-directive]="b.somedata">
    <label class="custom-control-label" for="cb{{t.id}}">&nbsp;</label>
  </div>
  ...
</tr>
Run Code Online (Sandbox Code Playgroud)

在 my-directive 指令代码中:

@HostListener('change') onChange() {
  // do some stuff...
}
Run Code Online (Sandbox Code Playgroud)

问题

想要发生的是quack()当任何人点击行时触发该功能,除非他们点击复选框。当他们选中或取消选中复选框时,我希望onChange()自定义指令中的函数被触发,我不想嘎嘎叫。

“嘎嘎!” 每次单击该行时,控制台中都会出现一次,这是正确的。奇怪的是,当我点击复选框时,我得到两个嘎嘎声,然后onChange()处理程序触发。我想要零个庸医,我希望有一个,但我得到了两个!

  • 顺便说一句,当我通过按空格键而不是单击来选中/取消选中复选框时,我仍然会遇到一个庸医。我无法想象点击事件来自哪里。

我添加(click)="$event.stopPropagation();"<input>元素中,认为这可以解决问题。当我单击复选框时,它使我归结为一个庸医。我想归零。 如何防止单击复选框传播click()触发 的事件quack()

  • 顺便说一句,在添加该片段后,用空格键切换复选框会产生零嘎嘎声。

wor*_*joe 11

答案

我错误地认为它是 Bootstrap 4 自定义复选框无关紧要——实际上这是我问题的关键。在 Bootstrap 4 的这种用法中,<input>本身是不可见的!您在屏幕上看到的看起来像复选框的东西实​​际上是由 CSS 生成的。因此,该click事件首先不属于该<input>元素。

为了解决这个问题,我移到(click)="$event.stopPropagation();"<div>包装自定义复选框的元素,如下所示:

<tr *ngFor="let t of things" (click)="quack()">
  ...
  <div class="custom-control custom-checkbox" (click)="$event.stopPropagation();">
    <input type="checkbox" class="custom-control-input" id="cb{{t.id}}" name="cb1" 
     [my-directive]="b.somedata">
    <label class="custom-control-label" for="cb{{t.id}}">&nbsp;</label>
  </div>
  ...
</tr>
Run Code Online (Sandbox Code Playgroud)

如果我使用普通复选框而不是这些 Bootstrap 4 自定义复选框,那么 ConnorsFan 提到的任何一个解决方案都可以完美运行。