In the below example, I have a simple <table>
with a checkbox inside it. I have click events on the td, tr and checkbox. I want to be able to click the checkbox and stop the bubbling to the td and tr. A simple "event.stopPropagation()" works great.
The problem is that if I want to connect a <label>
to the checkbox using "htmlFor", the events won't stop bubbling when the label is clicked (even though it still works as expected with the checkbox itself is clicked). And even more strangely, the bubbling seems to happen in a weird order (as in Checkbox click is received last!).
Here's the code:
var Hello = React.createClass({
func1(e){
console.log('tr was clicked')
},
func2(e){
console.log('td was clicked')
},
func3(e){
e.stopPropagation();
console.log('Checkbox was clicked')
},
render: function() {
return <table>
<tbody>
<tr onClick={this.func1}>
<td onClick={this.func2}>
<input id="thing" type="checkbox" onClick={this.func3} />
<label htmlFor="thing"> label for checkbox</label>
</td>
</tr>
</tbody>
</table>;
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
...And here's the Fiddle: https://jsfiddle.net/69z2wepo/52785/ (View the console for the click events)
To stop an event from further propagation in the capturing and bubbling phases, you call the Event. stopPropation() method in the event handler. Note that the event. stopPropagation() method doesn't stop any default behaviors of the element e.g., link click, checkbox checked.
event.stopPropagation() This will stop any parent component's event from firing. To use this: Make sure to pass the event object as a parameter. Use the stopPropagation method on the event object above your code within your event handler function.
React: stopPropagation We extended one of the previous examples by using the stopPropagation() method on an event. This way, when the button gets clicked, the event does not bubble up and does not trigger the event handler of the surrounding container element.
Event.stopPropagation() The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases.
The label
doesn't have a click handler of it's own, and can't stop propagation, so when you click the label
normal event bubbling takes place. This means that all the parent's event handlers are invoked in the correct order. In addition, because of the htmlFor
, the checkbox
click handler is also triggered, but not as part of the event bubbling.
To solve the problem, add a separate click handler to the label
that only includes .stopPropgation()
(demo):
var Hello = React.createClass({
func1(e){
console.log('tr was clicked')
},
func2(e){
console.log('td was clicked')
},
func3(e){
e.stopPropagation();
console.log('Checkbox was clicked')
},
stopLabelPropagation(e) {
e.stopPropagation();
},
render: function() {
return <table>
<tbody>
<tr onClick={this.func1}>
<td onClick={this.func2}>
<input id="thing" type="checkbox" onClick={this.func3} />
<label htmlFor="thing" onClick={ this.stopLabelPropagation }>label for checkbox</label>
</td>
</tr>
</tbody>
</table>;
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With