Why are div elements not re-indexed after removing one of them with JavaScript?

Viewed 63

I want to remove a div with the index == 0 each time I click on one of the elements with the class .slide.

It works the first time, but when I try again, the code tries to remove the element that has been previously removed, but I can still log the element to the console.

I thought that index "0" will be assigned to the next div sharing the same class, so the next time I click, this next div would be deleted.

What am I missing here?

Here is my code:

    let slides = document.querySelectorAll(".slide")
     
    slides.forEach((el) => {
        el.addEventListener("click", () => {
            // remove the first div 
            slides[0].remove() 

            // the element above has been removed, but I still can log it out (?)
            // and it seems to keep the index [0]       
            console.log(slides[0])
        })
    })
4 Answers

I believe you have deleted the element from the DOM, but have not removed it from the array. Try using the shift array method to remove the first element that you are deleting.

slides.forEach((el)=>{
    el.addEventListener("click",()=>{
        slides.shift().remove();
    })
}

This will do exactly what you expect - and will only get from the live HTMLCollection that getElementsByClassName returns:

let slides = document.getElementsByClassName("slide")

for (const slide of slides) {
  slide.addEventListener("click", () => {
    // remove the first div 
    slides[0].remove()
    console.log(slides[0])
  })
}
<div class="slide">0</div>
<div class="slide">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
<div class="slide">5</div>

After reading your question and comments, I think this is what you are trying to do.

Add a new div by clicking the add button and delete a div by clicking on the div.

The number of the new div will always be the current length of the array of divs.

let slides = document.getElementsByClassName("slide")
let container = document.querySelector(".container");
let addButton = document.querySelector("button");

[0,1,2,3,4].forEach((el) => { 
  const newDiv = createNewDiv(el);
  container.append(newDiv);
});

addButton.addEventListener("click", () => {
  const newDiv = createNewDiv(slides.length);
  container.append(newDiv);
  console.log("length of slides:", slides.length);
});

function removeDiv(e) {
  e.target.remove();
  console.log("length of slides:", slides.length);
}

function createNewDiv(slideId) {
  const newDiv = document.createElement("div");
  newDiv.classList.add("slide");
  const newContent = document.createTextNode(slideId);
  newDiv.appendChild(newContent);
  newDiv.addEventListener("click", removeDiv);
  return newDiv;
}
.container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.slide {
  height: 100px;
  width: 100px;
  background-color: red;
  border: solid 2px black;
  font-size: 3em;
}
<button>Add a slide</button>
<div class="container">
</div>

Based on your feedback, and the research I did ( on live and static node lists ) I came up with the following solution to my question. As you can see I am not using a querySelection nodelist anymore as this type is static. Instead, I went for a getElementsByClassName HTML collection. What do you think of this? Thanks for your precious support!

let sliderCollection = document.getElementsByClassName("slider") // HTML COLLECTION

let arrayCollection =[] 
arrayCollection = Array.from(sliderCollection) // HTML COLLECTION turned into an array
console.log("initial number of divs:",arrayCollection.length) // initial number of divs

arrayCollection.forEach( (el)=>{
    el.addEventListener('click',()=>{
   sliderCollection[0].remove() // remove always the first element
   arrayCollection = Array.from(sliderCollection) // refill the array with the updated number of divs
   console.log(arrayCollection.length) // keep track of the current number of divs
    })
})
.container {
    display: flex;
    flex-direction: row;
  }
  
  .slider {
    height: 100px;
    width: 100px;
    background-color: red;
    border: solid 2px black;
    font-size: 3em;
  }
<div class="container">
            <div class="slider">0</div>
            <div class="slider">1</div>
            <div class="slider">2</div>
            <div class="slider">3</div>
            <div class="slider">4</div>
            <div class="slider">5</div>
          </div>

Related