0

Every time when a button is clicked, a checkmark will be displayed. If the clicked button is not active, the checkmark is removed. Also when the button is clicked the "load dynamic content"-button will be displayed. There is a problem when dynamic content is loaded. After loading, checkmarks appear.But removing a checkmark does not work. I use a nested event listener for dynamic content. When I check console log after loading, button class elements has not changed. I cannot figure out how to solve this. Any advice?

const checkMarks = document.querySelectorAll('.ck');
// Nested event delegation
document.querySelector('.parent').addEventListener('click', function(e){
  if(e.target.classList.contains('btn-link')){
    // Hide checkmark if not active button
    checkMarks.forEach(function(check, index){
      check.classList.remove('show');
    });
    // Display checkmark
    e.target.closest('div').querySelector('.ck').classList.add('show');
    // Display load dynamic button 
    document.querySelector('.load-content').classList.add('show');
  }
});

document.querySelector('.load-content').addEventListener('click', function(){
    document.querySelector('.parent').innerHTML = '<div><button class="btn-link btn4">Button 4</button><span class="ck">checked</span></div><div><button class="btn-link btn5">Button 5</button><span class="ck">checked</span></div><div><button class="btn-link btn6">Button 6</button><span class="ck">checked</span></div>'
});
.parent{
  padding: 30px;
}
.parent .footer{
  margin-top: 30px;
  margin-bottom: 30px;
  display: flex;
}
.btn-link{
  display: block;
  width: 100px;
  padding: 15px;
  margin-bottom: 15px;
}
.load-content{
  display: none;
  padding: 15px;
}
.load-content.show{
  display: block;
}
.ck{
  display: none;

}
.ck.show{
  display: block;
}
<div class="parent">
<div><button class="btn-link btn1">Button 1</button><span class="ck">checked</span></div>
<div><button class="btn-link btn2">Button 2</button><span class="ck">checked</span></div>
<div><button class="btn-link btn3">Button 3</button><span class="ck">checked</span></div>
</div>
<div class="load"><button class="load-content">Load dynamic content</button></div><div>

jsfiddle

Sebu
  • 3
  • 3
  • Your title and tags already mention event delegation, but your code doesn't use that approach? – Bergi Jan 20 '22 at 11:27

2 Answers2

0

The click handler on .load-content removes/replaces nodes present in your code and create new nodes. But these new nodes do not get picked up because this code:

const checkMarks = document.querySelectorAll('.ck');

Runs only one time and picks the checkmarks present at the page load. Try moving this expression inside .parent click handler to see if that helps.


Ideally you should be removing the click handler on .parent inside your .load-content click handler. Those handlers are still there and this presents memory leaks. You should be able to fix this by converting your anonymous click handler of .parent into a named function. Then you can simply use removeEventListener and addEventListener to remove and re-add the handlers.

user3056783
  • 2,265
  • 1
  • 29
  • 55
0

According to MDN: The Element method querySelectorAll() returns a static (not live) NodeList representing a list of elements matching the specified group of selectors.

So I changed that to getElementsByClassName, also the loop process, from forEach to for loop, here you go.

const checkMarks = document.getElementsByClassName('ck'); // Changed that

// Nested event delegation
document.querySelector('.parent').addEventListener('click', function(e){
  if(e.target.classList.contains('btn-link')){
    // Hide checkmark if not active button
    for(let i = 0; i < checkMarks.length ; i++){ // Also that changed, as forEach doesn't work for getElementsByClassName.
      checkMarks[i].classList.remove('show');
    };
    // Display checkmark
    e.target.closest('div').querySelector('.ck').classList.add('show');
    // Display load dynamic button 
    document.querySelector('.load-content').classList.add('show');
  }
});

document.querySelector('.load-content').addEventListener('click', function(){
    document.querySelector('.parent').innerHTML = '<div><button class="btn-link btn4">Button 4</button><span class="ck">checked</span></div><div><button class="btn-link btn5">Button 5</button><span class="ck">checked</span></div><div><button class="btn-link btn6">Button 6</button><span class="ck">checked</span></div>'
});
.parent{
  padding: 30px;
}
.parent .footer{
  margin-top: 30px;
  margin-bottom: 30px;
  display: flex;
}
.btn-link{
  display: block;
  width: 100px;
  padding: 15px;
  margin-bottom: 15px;
}
.load-content{
  display: none;
  padding: 15px;
}
.load-content.show{
  display: block;
}
.ck{
  display: none;

}
.ck.show{
  display: block;
}
<div class="parent">
<div><button class="btn-link btn1">Button 1</button><span class="ck">checked</span></div>
<div><button class="btn-link btn2">Button 2</button><span class="ck">checked</span></div>
<div><button class="btn-link btn3">Button 3</button><span class="ck">checked</span></div>
</div>
<div class="load"><button class="load-content">Load dynamic content</button></div><div>
Feki Hamza
  • 307
  • 1
  • 7