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>
4
Answers
You can’t use
i
inaddCountry
. It’s a global variable, not closed over the loop iteration.You need to put a closure into the loop, and then pass
i
as an argument toaddCountry()
.Using event delegation and data attributes you can avoid having to add multiple event handlers.
You are doing a small mistake at event binding. Update this line of the code:-
Here’s another approach it seems easy to understand but don’t hesitate if you have any question.
This solution avoid to always use innerHTML!
I don’t understand if you want to duplicate nodes or just create a document as specified and add a listener to it.
in the
clickHandler()
method you can easily do what you want…Duplicate an Object, add the destination to a cart…
If you want to see the logs, click on "Full page" for the snippet.
Best regards.