Reputation: 986
I am trying to create a button list with automatically assigned onclick events.
document.getElementById('buttonList').innerHTML = '';
for(var $c = 0; $c < $buttons.length; $c++) {
document.getElementById('buttonList').innerHTML += '<li><button id="button-' + $c + '">' + $buttons[$c].text + '</button></li>';
document.querySelector('#button-' + $c).onclick = (function($index) {
return function() {
console.log($index);
};
})($c);
}
In my opinion, if i click a button it should log 0/1/2/3/... But none of the buttons is working, except the last one. The last button returns the right index.
So my question, what is wrong?
Upvotes: 1
Views: 106
Reputation:
When you use innerHTML += ...
, it destroys the older onclick
handlers. You can fix this in one of two ways:
Use appendChild
instead of innerHTML += ...
:
document.getElementById('buttonList').innerHTML = '';
for(var $c = 0; $c < $buttons.length; $c++) {
var li = document.createElement('li');
var button = document.createElement('button');
button.setAttribute('id', 'button-' + $c);
button.innerHTML = $buttons[$c].text;
button.onclick = (function($index) {
return function() {
console.log($index);
};
})($c);
li.appendChild(button);
document.getElementById('buttonList').appendChild(li);
}
Generate the HTML first, then add the event handlers all at once:
document.getElementById('buttonList').innerHTML = '';
for(var $c = 0; $c < $buttons.length; $c++) {
document.getElementById('buttonList').innerHTML += '<li><button id="button-' + $c + '">' + $buttons[$c].text + '</button></li>';
}
for(var $c = 0; $c < $buttons.length; $c++) {
document.querySelector('#button-' + $c).onclick = (function($index) {
return function() {
console.log($index);
};
})($c);
}
Upvotes: 2
Reputation: 8715
When you modify the innerHTML
property, the element gets rerendered, so the elements, that you've bind the onclick
to, do not exist in the DOM anymore (except the last one).
From MDN:
Removes all of element's children, parses the content string and assigns the resulting nodes as children of the element.
If you still want to use innerHTML
, the solution is to create a container element (<li>
), append it to your list and then modify its innerHTML
:
document.getElementById('buttonList').innerHTML = '';
for (var $c = 0; $c < $buttons.length; $c++) {
var liItem = document.createElement("li");
document.getElementById('buttonList').appendChild(liItem);
liItem.innerHTML = '<button id="button-' + $c + '">' + $buttons[$c].text + '</button>';
console.log(document.querySelector('#button-' + $c));
document.querySelector('#button-' + $c).onclick = (function ($index) {
return function () {
console.log($index);
};
})($c);
}
Upvotes: 2