I have a click event on li tag and then in that li i have another nested li.
When clicked on parent li everything works fine. But onclick nested or child li the parent li click event is fired.
I have used event.stopPropagation() method but it does not work in my case.
$("li").on("click",function() {
console.log(this.firstChild.textContent)
})
$('#testUl > li').on('click', function(e) {
e.stopPropagation();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<ul id="testUl">
<li>
<a href="#">Test A</a>
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
$('#testUl .innerUl li').on('click', function(e) {
e.stopPropagation();
});
// or
$('#testUl li').on('click', function(e) {
e.stopPropagation();
});
$('#testUl > li').on('click', function(e) {
alert('test');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- #testUl -->
<ul id="testUl">
<!-- #testUl > li -->
<li>
<!-- #testUl > li > a or #testUl a -->
<a href="#">Test A</a>
<!-- #testUl > li > .innerUl or #testUl .innerUl -->
<div class="innerUl">
<!-- #testUl > li > .innerUl > ul or #testUl ul -->
<ul>
<!-- #testUl > li > .innerUl > ul > li or #testUl li or #testUl .innerUl li or .innerUl li -->
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
You are using a wrong selector for stop propagation
When you use #testUl > li you call the first li child element, but you have li elements inside your li on #testUl, so call #testUl li or #testUl .innerUl li
You can compare e.target which is element that have click event and e.currentTarget that is element you actually clicked. If they don't match then you return without performing rest of function
$('#testUl > li').on('click', (e) => {
if (e.target !== e.currentTarget) {
return;
}
console.log('parent');
});
$('.innerUl li').on('click', (e) => {
if (e.target !== e.currentTarget) {
return;
}
console.log('child');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="testUl">
<li>
Test A
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
Without jQuery you can use event delegation and determine to act using Element.closest()
document.addEventListener(`click`, handle);
function handle(evt) {
console.clear();
if (!evt.target.closest(`.innerUl`) && evt.target.closest(`#testUl`)) {
console.log(`You clicked (something within) the first li of ul#testUl`);
}
}
<ul id="testUl">
<li>
<a href="#">Test A</a>
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>
Same idea with jQuery
$("#testUl").on("click", evt => {
console.clear();
if (!evt.target.closest(`.innerUl`) && evt.target.closest(`#testUl`)) {
console.log(`You clicked ${evt.target.outerHTML}`);
}
});
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js">
</script>
<ul id="testUl">
<li>
<a href="#">Test A</a>
<div class="innerUl">
<ul>
<li>Inner A</li>
<li>Inner B</li>
<li>Inner C</li>
</ul>
</div>
</li>
</ul>