3

I have a table with multiple rows . Each row has an onClick property which calls the class handleClick method. Each has multiple child elements. NONE of the child elements have an onClick property, and so they should not trigger the handleClick method.

Here is the code:

...

export class EventRow extends Component {

    ...

    handleClick = (e) => {
        e.preventDefault();
        console.log(e.target.id);
        console.log(e.target.nodeName);
    }

    ...

    render () {
        return (
            <tr id = { "tr" + this.props.eventdefinition.event_id } className = "noselect" onClick = { this.handleClick.bind(this) }>
                <td className = "noselect">{this.props.eventdefinition.event_name}</td>
                <td>
                <div className = "custom-control custom-checkbox tdDiv noselect">
                    <input type="checkbox" className = "custom-control-input" id = { "customCheck" + this.props.eventdefinition.event_id } readOnly checked = {this.props.eventdefinition.recurring} />
                    <label className = "custom-control-label" htmlFor = {"customCheck" + this.props.eventdefinition.event_id}></label>
                </div>
                </td>
                <td>
                <div className = "custom-control custom-switch tdDiv noselect">
                    <input type="checkbox" className = "custom-control-input" id = { "customSwitch" + this.props.eventdefinition.event_id } checked = {this.props.eventdefinition.active_for_generation} onChange = { this.onChange }/>
                    <label className = "custom-control-label" htmlFor = {"customSwitch" + this.props.eventdefinition.event_id}></label>
                </div>
                </td>
            </tr>
        );
    }
}

...

Right now you can see that in the handleClick method, there are two console.log statements. When I click on my rows, I would expect that in my console I would get an id such as tr3 and a node name TR, but instead I get the id of whatever child was also clicked which is normally black , and the node name of whatever child was also clicked TD or INPUT or LABEL. What is going on with my event triggers?

FlamePrinz
  • 490
  • 1
  • 5
  • 20
  • I should note that there is a very easy solution to my problem which is to use whatever child element is clicked to figure out which row was clicked, but this is more of a hack and does not solve my confusion about why the children are triggering the onClick. – FlamePrinz Nov 23 '20 at 19:49
  • It's called [Event Bubbling in JavaScript and Event Propagation](https://www.sitepoint.com/event-bubbling-javascript/). Please check it out. – Praveen Kumar Purushothaman Nov 23 '20 at 19:49

2 Answers2

2

It's called Event Bubbling in JavaScript and Event Propagation. Please check it out. So what happens is, the event is passed to the parents, something like this:

bubble

And here's an animation:

event

The bubbling affects all the elements upto the parent, which is body. Here you have the event target, which will contain the element that this event is triggered from. In your case, it could be the clicked TD or INPUT or LABEL.

You can also read more about this on Event Handling.

Stopping the bubbling

You can stop the propagation of event from the triggered element to the above parent or child by using either of the below based on the scenario:

event.stopPropagation();
event.stopImmediatePropagation();

To know more about the differences, please check out stopPropagation vs. stopImmediatePropagation.

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
1

You can prevent this by calling event.stopPropagation();, this happens because the click event propagates through the DOM tree triggering the click event of parent elements.

Sherif Wael
  • 435
  • 2
  • 9