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=".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>
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./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>
Share
Improve this question
edited Nov 10, 2021 at 12:16
mplungjan
178k28 gold badges182 silver badges240 bronze badges
asked Nov 10, 2021 at 12:10
ShakirShakir
1031 silver badge10 bronze badges
4
- $('#testUl > li') is probably the wrong selector. If you want the same function for parent and children: $('#testUI li') – Dov Rine Commented Nov 10, 2021 at 12:13
-
Your code has the stopPropagation on the parent element. Child elements get click events first. This is assuming you have a second event on the child
li
, not included in your question. Otherwise there's only a parent event anyway. – fdomn-m Commented Nov 10, 2021 at 12:13 - I made you a snippet. Please add YOUR function that you do not want executed – mplungjan Commented Nov 10, 2021 at 12:17
- (note: 2nd event was added via edit, needs to be updated by OP, via an edit) – fdomn-m Commented Nov 10, 2021 at 12:27
4 Answers
Reset to default 3Without 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./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./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 pare 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./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>
You can try with stopImmediatePropagation()
See here: https://developer.mozilla/en-US/docs/Web/API/Event/stopImmediatePropagation