Having the following structure:
<div >
<div>
<a onClick="doParentStuff()">
<div>
<i onClick="doChildStuff()"></i>
</div>
</a>
</div>
</div>
Now, when the child element (icon) is clicked it logs the content of doChildStuff()
but afterwards it also logs the content of doParentStuff()
.
Is there a way to call doChildStuff
only when the icon is clicked and call doParentStuff
when everything else inside the-parent
div is clicked?
CodePudding user response:
Avoid the use of Event.stopPropagation()
(unless you really, really know what you're doing).
An application, or third party code, should never stop or prevent an event to propagate throughout the application layers / components.
Instead, change your logic to implement a third function (like doStuff
) that will trigger a desired function depending on the Event.target.closest()
match
const doChildStuff = () => {
console.log("child stuff");
};
const doParentStuff = () => {
console.log("parent stuff");
};
const doStuff = (ev) => {
if (!ev.target.closest(".icon")) {
doParentStuff();
}
doChildStuff();
};
document.querySelectorAll(".anchor").forEach(elAnchor => {
elAnchor.addEventListener("click", doStuff);
});
<div >
<div>
<a >
<div>
Link
<i >icon</i>
</div>
</a>
</div>
</div>
Also, stop using HTML inline on*
attribute handlers. Such code is hard to maintain and debug. JavaScript should be in one place only, and that's the respective tag or file. Use addEventListener instead.
CodePudding user response:
When the child is clicked, you must stopPropagation
of the event:
function doChildStuff(e) {
e.stopPropagation();
console.log('child clicked');
}
function doParentStuff() {
console.log('parent clicked');
}
<div >
<div>
<a onClick="doParentStuff()">
<div>
Test
<button onClick="doChildStuff(event)">Child</button>
</div>
</a>
</div>
</div>