Javascript event Listeners are not working on updating the DOM.
**HTML CODE: **
<div >
</div>
**JAVASCRIPT CODE: **
function showList(num) {
const taskBox = document.querySelector('.task-list');
let listHtml = "";
for(let i =1;i<=num;i ){
listHtml = `
<li >Hello ${i}</li>
`;
}
taskBox.innerHTML = listHtml;
}
showList(5);
const listItem = document.querySelectorAll('.list-item');
listItem.forEach((item) => {
item.addEventListener('click', (e) => {
console.log(e.target.innerText);
showList(4);
});
});
With this code event Listener just working once. After that it is not working and not even showing error. So why this is happening. How to udpation of the DOM affecting eventlistener exactly.
I have faced this problem multiple times, I solved this by using onclick()
function on each elmeent, but i never got solution of why it is not working in this way.
CodePudding user response:
The reason is that after you invoke showList()
again,you have replaced the old elements with new elements,and they do not have event binds,you need to add click event again
const listItem = document.querySelectorAll('.list-item');
listItem.forEach((item) => {
item.addEventListener('click', (e) => {
console.log(e.target.innerText);
showList(4);// after create new element,need to add click event again
});
});
function showList(num) {
const taskBox = document.querySelector('.task-list');
let listHtml = "";
for(let i =1;i<=num;i ){
listHtml = `<li >Hello ${i}</li>`;
}
taskBox.innerHTML = listHtml;
addClickEvent(); // add click event again
}
function addClickEvent(){
const listItem = document.querySelectorAll('.list-item');
listItem.forEach((item) => {
item.addEventListener('click', (e) => {
console.log(e.target.innerText);
showList(4);
});
});
}
showList(5);
<div >
</div>
CodePudding user response:
it's because listener is removed... if I follow the steps
showList(5);
will render the list after that
const listItem = document.querySelectorAll('.list-item');
listItem.forEach((item) => {
item.addEventListener('click', (e) => {
console.log(e.target.innerText);
showList(4);
});
});
this will add listener to each item. but if you click, it will call showList again and it will rerender the list and remove the listener..
so if you want to the listener is added every render, move it to the showList function
function showList(num) {
const taskBox = document.querySelector('.task-list');
let listHtml = "";
for(let i =1;i<=num;i ){
listHtml = `
<li >Hello ${i}</li>
`;
}
taskBox.innerHTML = listHtml;
const listItem = document.querySelectorAll('.list-item');
listItem.forEach((item) => {
item.addEventListener('click', (e) => {
console.log(e.target.innerText);
showList(4);
});
});
}
CodePudding user response:
Here's an implementation using @VLAZ's event delegation suggestion.
Put the click listener on the container and use the event to identify what was clicked.
function showList(num) {
const taskBox = document.querySelector('.task-list');
let listHtml = "";
for(let i =1;i<=num;i ){
listHtml = `<li >Hello ${i}</li>`;
}
taskBox.innerHTML = listHtml;
}
// listen on the container and use the
// event to figure out what was clicked
// instead of adding a listener on every
// child.
document.querySelector('.task-list').addEventListener(
'click',
(e) => { console.log(e.target.innerText) }
)
showList(5);
<div >
</div>