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}}"> </label>
</div>
...
</tr>
在my-directive指令代码中:
@HostListener('change') onChange() {
// do some stuff...
}
问题
我希望发生的是 quack()
函数在任何人单击该行时触发,除非 他们单击复选框。当他们选中或取消选中复选框时,我希望自定义指令中的 onChange()
函数触发,我不想嘎嘎作响。
每次单击该行时,"quack!" 都会在控制台中出现一次,这是正确的。奇怪的是,当我单击复选框时,我得到 两个 嘎嘎声,然后 onChange()
处理程序触发。我想要零个江湖医生,我期待一个,但我有两个!
- 顺便说一下,当我 check/uncheck 通过按空格键而不是单击来选中复选框时,我仍然会听到嘎嘎声。我无法想象点击事件来自哪里。
我在 <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}}"> </label>
</div>
...
</tr>
如果我使用普通复选框而不是这些 Bootstrap 4 个自定义复选框,ConnorsFan 提到的任何一种解决方案都可以完美运行。
我正在使用 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}}"> </label>
</div>
...
</tr>
在my-directive指令代码中:
@HostListener('change') onChange() {
// do some stuff...
}
问题
我希望发生的是 quack()
函数在任何人单击该行时触发,除非 他们单击复选框。当他们选中或取消选中复选框时,我希望自定义指令中的 onChange()
函数触发,我不想嘎嘎作响。
每次单击该行时,"quack!" 都会在控制台中出现一次,这是正确的。奇怪的是,当我单击复选框时,我得到 两个 嘎嘎声,然后 onChange()
处理程序触发。我想要零个江湖医生,我期待一个,但我有两个!
- 顺便说一下,当我 check/uncheck 通过按空格键而不是单击来选中复选框时,我仍然会听到嘎嘎声。我无法想象点击事件来自哪里。
我在 <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}}"> </label>
</div>
...
</tr>
如果我使用普通复选框而不是这些 Bootstrap 4 个自定义复选框,ConnorsFan 提到的任何一种解决方案都可以完美运行。