Search code examples
javascript

Eventlistener for collection


I'm trying to add an eventlistener for a button collection inside of a for loop, but I'm kind of lost because in following example the eventlistener only works for the last button in the collection, and my country in addCountry function is undefined. I would appreciate any kind of feedback or help.

I have tried to console.log(i) and obviously it is working as it should. And I have console.log('.add'[i]) and that is displaying the button element so I don't understand how this works really.

let countries = ["Sweden", "Norway", "Denmark", ]

const main = document.getElementById("maincontent")
const cart = document.getElementById('cart')

for (i = 0; i < countries.length; i++) {

  addContent()

  document.querySelectorAll('.add')[i].addEventListener('click', addCountry)
}

function addContent() {
  main.innerHTML += `<div>
  <h1>${countries[i]}</h1>
  <div class="one hide">
      <p>Some text</p>
      <button class="add">Add</button>
  </div>
  </div>`
}

function addCountry() {
  cart.innerHTML = `<div>
<h1>${countries[i]}</h1>
<div class="one hide">
    <p>Some text</p>
    <button class="delete">Delete</button>
</div>
</div>`
}
<main id="maincontent">

</main>
<div id="cart">

</div>


Solution

  • Using event delegation and data attributes you can avoid having to add multiple event handlers.

    let countries = ["Sweden", "Norway", "Denmark", ]
    
    const main = document.getElementById("maincontent")
    const cart = document.getElementById('cart')
    
    const html = countries.map(addContent);
    main.innerHTML = html.join('');
    
    main.addEventListener("click", function (e) {
      const btn = e.target.closest('[data-country]');
      if (!btn) return;
      const country = btn.dataset.country;
      addCountry(country);
    });
    
    cart.addEventListener("click", function (e) {
      const btn = e.target.closest('.delete');
      if (!btn) return;
      btn.closest(".wrapper").remove();
    });
    
    
    function addContent(country) {
      return `
      <div>
        <h1>${country}</h1>
        <div class="one hide">
          <p>Some text</p>
          <button class="add" data-country="${country}">Add</button>
        </div>
      </div>`;
    }
    
    function addCountry(country) {
      cart.innerHTML += `
      <div class="wrapper">
        <h1>${country}</h1>
        <div class="one hide">
          <p>Some text</p>
          <button class="delete">Delete</button>
        </div>
      </div>`;
    }
    <main id="maincontent"></main>
    <div id="cart"></div>