skip to Main Content

I am dynamically appending divs to a parent wrapper by looping through an array. After appending the inner div I attach an onclick event listener to each inner div that prints out the id of each innerDiv. Why is the below code only printing the id of the last appended innerDiv?

let arr = ['a', 'b', 'c']

const wrapper = document.querySelector('.wrapper')

for (var i = 0; i < arr.length; i++) {
  wrapper.innerHTML += `<div class="container" id="${arr[i]}"></div>`
  
  let container = document.querySelector(`#${arr[i]}`)
  
  container.onclick = (e) => {
    console.log(e.target.id)
  }
}
.wrapper {
  display: flex;
  flex-direction: column;
  row-gap: 15px;
  width: 500px;
  border: 2px solid #000;
}

.container {
  width: 100%;
  height: 80px;
  cursor: pointer;
  background-color: blue;
}
<div class="wrapper"></div>

2

Answers


  1. When you add an element with this method (+=), after each loop it recreates all the elements inside the wrapper (when it concatenates the string and the innerHTML). This also means that the previously attached event listener (onclick) is removed, since it is "not the same" element anymore.

    To prevent this, you can use a different method to add the new divs:

    const newDiv = document.createElement('div')
    // set its properties, like className and id
    wrapper.appendChild(container);
    
    Login or Signup to reply.
  2. When you use innerHTML += ..., it indeed re-renders the entire content of the wrapper, and this process causes the loss of all previously attached events. The reason is that the innerHTML property sets or gets the HTML content within an element, and when you use the += operator, you are essentially overwriting the existing content with the new content, erasing any previously attached event listeners in the process.

    You can try try using insertAdjacentHTML():

    let arr = ['a', 'b', 'c']
    
    const wrapper = document.querySelector('.wrapper')
    
    for (var i = 0; i < arr.length; i++) {
      wrapper.insertAdjacentHTML('beforeend', `<div class="container" id="${arr[i]}"></div>`);
      
      let container = document.querySelector(`#${arr[i]}`)
      
      container.onclick = (e) => {
        console.log(e.target.id)
      }
    }
    .wrapper {
      display: flex;
      flex-direction: column;
      row-gap: 15px;
      width: 500px;
      border: 2px solid #000;
    }
    
    .container {
      width: 100%;
      height: 80px;
      cursor: pointer;
      background-color: blue;
    }
    <div class="wrapper"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search