0

I have a strange behavior in my very simple code. I want to remove() all buttons with the class btn from the DOM after a button has been clicked.

In my function removeAllBtns() I have two console outputs. The correct number of buttons is displayed. But the second element is always not deleted.

Why is that? I am probably missing something very simple here. Thanks in advance.

let btns = document.getElementsByClassName('btn');

for (var i = 0; i < btns.length; i++) {
  let button = btns[i];
  button.addEventListener('click', function (e) {  
    removeAllBtns();  
  });
}

function removeAllBtns() {  
  console.log('btns length',btns.length)
  for (let j = 0; j < btns.length; j++) {
    console.log(j, btns[j])
    btns[j].remove();
    
  }
}
.btn{
  color: red;
}
<button class="btn">1</button>   
<button class="btn">2</button>   
<button class="btn">3</button>
Maik Lowrey
  • 15,957
  • 6
  • 40
  • 79
  • 1
    `getElementsByClassName` returns a live HTMLCollection so as you delete elements the list shortens so later indexes no longer exist. – pilchard Dec 31 '21 at 13:05
  • 3
    Loop from the end to the beginning and remove the elements: [Looping through array and removing items, without breaking for loop](https://stackoverflow.com/questions/9882284). Or: [removing element from parent node with loop](https://stackoverflow.com/questions/58420675) – adiga Dec 31 '21 at 13:05
  • 1
    Use [event delegation](//developer.mozilla.org/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation) instead of assigning multiple event listeners — it’s more maintainable, and applies to dynamically added elements. E.g., use an [event argument](//developer.mozilla.org/docs/Web/API/EventTarget/addEventListener#The_event_listener_callback)’s [`target`](//developer.mozilla.org/docs/Web/API/Event/target). See [the tag info](/tags/event-delegation/info) and [What is DOM Event delegation?](/q/1687296/4642212). – Sebastian Simon Dec 31 '21 at 13:07
  • 1
    @SebastianSimon `if (target.closest(".btn")) for (const button of document.querySelectorAll(".btn")) button.remove();` @OP: qsa returns a non-live NodeList. – Thomas Dec 31 '21 at 13:21
  • 1
    Alternatively: `addEventListener("click", ({ target }) => { const button = target.closest(".btn"); if(button){ Array.from(document.querySelectorAll(".btn")).forEach((elem) => elem.remove()); } });`. No other JS necessary. – Sebastian Simon Dec 31 '21 at 13:28

0 Answers0