Royi Namir
Royi Namir

Reputation: 148524

e.stopPropagation() is not working as expected?

I have a simple table :

enter image description here

The TR has <tr onclick='alert("row");'>

And the button has :

$("body").on('click',".b",function (e){
  alert('button');
  e.stopPropagation();
});

However - Although I wrote e.stopPropagation(); it still alerts : "row , button".

Now , I know that the event handler is attached to the body and the selector is checked against it ( the click start at the button and move up to the body , just like $.live use to do but against document...).

But the checking should be for the button click and not for the TR click.

It seems that while i'm clicking , it propagates to the "body" ( because I attached event handler to it) and while its way up to the body it activates the click on the TR.

What is going on here? How can I keep my code ( attach to body) and still have only alert of "button".

P.s.

I know I can simply do :

$(".b").on('click',function (e){
  alert('button');
  e.stopPropagation();

});

but I want to know why my current(!) code doesnt work.

Upvotes: 23

Views: 67993

Answers (4)

Zia Khan
Zia Khan

Reputation: 425

This is the solution worked properly in my case in Angular using material select

import {Directive, HostListener} from "@angular/core";

@Directive({
    selector: "[click-stop-propagation]"
})
export class ClickStopPropagation
{
    @HostListener("click", ["$event"])
    public onClick(event: any): void
    {
        event.stopPropagation();
    }
}

In template use it like this

(click)="onClick($event)

Upvotes: -1

Tahir Alvi
Tahir Alvi

Reputation: 994

If you want to stop the event propagation from child to parent, then you may use this code.

Let's say you have a select, button, or any other click event inside a div etc. Then Write the below code code on onclick method.

<button type="button" onclick="event.cancelBubble = true;" >Click Me </button>

or

<button type="button" onclick="event.cancelBubble = true; doSomething();" >Click Me </button>

you can replace button with any HTML input or other element.

in your specific case use

<tr onclick='event.cancelBubble = true; alert("row");'>

Upvotes: 2

elclanrs
elclanrs

Reputation: 94101

...but I want to know why my current(!) code doesnt work.

From jQuery docs, on event.stopPropagation with event delegation:

Since the .live() method handles events once they have propagated to the top of the document, it is not possible to stop propagation of live events. Similarly, events handled by .delegate() will propagate to the elements to which they are delegated; event handlers bound on any elements below it in the DOM tree will already have been executed by the time the delegated event handler is called. These handlers, therefore, may prevent the delegated handler from triggering by calling event.stopPropagation() or returning false.

live and delegate are now on so this applies.

Upvotes: 9

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382150

The problem is that you're attaching the event handler to the body, even if it delegates to the .b element. This event handler is called only after the tr event handler is called, so it's too late to stop propagation.

As I suppose you want to deal with dynamically added elements and can't simply bind the event handler to the td, I can suggest you this :

$('body').on('click',"tr",function (e){
  alert('row');
});
$("body").on('click',".b",function (e){
  alert('button');
  e.stopPropagation();
});

Demonstration

Upvotes: 20

Related Questions