Angular中checkbox有change事件时,TR click事件的stopPropagation()怎么办?

In Angular, how to stopPropagation() of TR click event when checkbox has change event?

我正在使用 Angular 6. 我有一个带有点击事件的 table 行 (<TR>)。出于测试目的,假设事件将 "quack!" 打印到控制台。这是 HTML:

<tr *ngFor="let t of things" (click)="quack()">
  ...
</tr>

组件中:

quack() {
  console.log('quack!');
}

现在,在这一行中我有一个复选框。这是一个 Bootstrap 4 自定义复选框,但我认为这不是我需要解决的问题的 material。该复选框有一个自定义指令,它添加了一个 change 事件处理程序(不是 click 事件)。 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>

在my-directive指令代码中:

@HostListener('change') onChange() {
  // do some stuff...
}

问题

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

每次单击该行时,"quack!" 都会在控制台中出现一次,这是正确的。奇怪的是,当我单击复选框时,我得到 两个 嘎嘎声,然后 onChange() 处理程序触发。我想要零个江湖医生,我期待一个,但我有两个!

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

答案

我错误地认为它是一个 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>

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