I am using event delegation on my project but for some reason it does not works as expected.
It may seem like a duplicated question but searching for days I have not found the solution so it is not as clear, even in a course I am taking at UDEMY this is not addressed.
The html structure is like this:
<div class="users-list"> <a class="useruid" id='. $row['unique_id'] .'> <div class="content"> <img src="php/images/'. $row['img'] .'" alt=""> <div class="details"> <span>'. $row['fname']. " " . $row['lname'] .'</span> <p>'. $you . $msg .'</p> </div> </div> <div class="status-dot '. $offline .'"><i class="fas fa-circle"></i> </div> </a> </div>
The vars with the dollar sign are php variables and everything inside “users-list” <div>
is added dynamically to the DOM (that part works well).
The problem comes when handling the event listener in javascript as follows:
const ulist = document.querySelector(".users-list"); ulist.addEventListener("click", (e) => { e.preventDefault(); console.log(e.target); if (e.target.classList.contains("useruid")) { console.log(e.target.id); } });
I need to get the id number inside the element to use it in another part of the program but it will only be captured if I click on the outer boundaries of the box and most of the time only the <span>
and the <p>
elements are the ones that will capture the click.
What do I’m missing here, isn’t the click suppose to bubble up all the way up passing through the <a>
element not matter where I click in that box?
I’ve searched on other questions here and everywhere online for days but can’t find a clear solution. Maybe my approach is incorrect, I don’t know really.
Adding additional clarification
using this has the same problem:
if (e.target.matches("a.useruid")) { console.log(e.target.id); }
Advertisement
Answer
What do I’m missing here, isn’t the click suppose to bubble up all the way to the
<a>
element not matter where I click in that box?
No. It bubbles up to <div class="users-list">
because that is where the event listener is bound.
The target
is the element that triggered the event.
You need to change your logic from does the clicked element have the class to does the clicked element or one of its ancestors have the class.
You can do that with closest
.
const ulist = document.querySelector(".users-list"); ulist.addEventListener("click", (e) => { e.preventDefault(); const anchor = e.target.closest(".useruid"); console.log(e.target); console.log(anchor) if (anchor) { console.log(anchor.id); } });
<div class="users-list"> <a class="useruid" id='one'> <div class="content"> <img src="//placekitten.com/100/100" alt=""> <div class="details"> <span>foo</span> <p>bar</p> </div> </div> </a> </div>