I'm using Angular 6. I have a table row (<TR>
) with a click event. For testing purposes let's just say the event prints "quack!" to the console. This is the HTML:
<tr *ngFor="let t of things" (click)="quack()">
...
</tr>
In the component:
quack() {
console.log('quack!');
}
Now, within this row I have a checkbox. It's a Bootstrap 4 custom checkbox but I don't think that's material to the problem I need to solve. That checkbox has a custom directive which adds a change event handler (not a click event). A simplified version of the HTML is:
<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>
In the my-directive directive code:
@HostListener('change') onChange() {
// do some stuff...
}
The problem
What I want to happen is for the quack()
function to fire when anyone clicks on the row, unless they click the checkbox. When they check or uncheck the checkbox, I want the onChange()
function in the custom-directive to fire, and I want no quacking.
The "quack!" appears in the console once each time I click on the row, which is correct. What's odd is that when I click on the checkbox I get two quacks and then the onChange()
handler fires. I'd like zero quacks, I expected one, but I got two!
- Incidentally, when I check/uncheck the checkbox by hitting the spacebar instead of clicking, I still get one quack. I can't imagine where the click event comes from.
I added (click)="$event.stopPropagation();"
to the <input>
element, thinking this would solve the problem. It brings me down to just one quack when I click on the checkbox. I'd like to get to zero. How can I prevent the click on the checkbox from propagating a click()
event that triggers a quack()
?
- By the way, after adding that snippet, toggling the checkbox with spacebar produces zero quacks.
The Answer
I was wrong to assume that it being a Bootstrap 4 custom checkbox was immaterial -- in fact that was the key to my problem. In this usage of Bootstrap 4, the
<input>
itself is invisible! The thing you see on screen that looks like a checkbox is actually generated by CSS. So theclick
event wouldn't belong to that<input>
element in the first place.To solve the problem, I moved
(click)="$event.stopPropagation();"
to the<div>
element that wraps the custom checkbox, like so:If I were using normal checkboxes instead of these Bootstrap 4 custom ones, either of the solutions mentioned by ConnorsFan would have worked perfectly.