5

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}}">&nbsp;</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.
6
  • I did not read everything but when Angular calls its custom (click) event, the browser event is already propagated so you can not stop it. Though you can still stop a click event by creating your own click event with plain javascript. Commented Aug 16, 2018 at 20:37
  • @Ploppy - Are you sure about that? I think that you can stop the propagation in the (click) event handler. Commented Aug 16, 2018 at 20:39
  • 1
    You can take a look at this stackblitz. It appears to work if we handle the click event in the directive and stop its propagation. Note: In my code example, I made sure that the id and the name of each check box is unique (but the click management worked without that change). Commented Aug 16, 2018 at 20:53
  • 1
    In this other stackblitz, I stop the propagation in the (click) event handler of the check box. Commented Aug 16, 2018 at 21:03
  • 1
    @ConnorsFan I altered the sample code to show a unique id/name for each checkbox, as you suggest. My problem turns out to be due to the Bootstrap 4 custom checkbox; your solutions work great for any normal checkbox. Commented Aug 17, 2018 at 2:13

1 Answer 1

13

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 the click 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:

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

If I were using normal checkboxes instead of these Bootstrap 4 custom ones, either of the solutions mentioned by ConnorsFan would have worked perfectly.

Sign up to request clarification or add additional context in comments.

1 Comment

I had the same problem with custom-checkbox and as workaround i used simple checkbox. Your answer makes that, i can use custom-checkbox again. Thank You! :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.