Skip to content Skip to sidebar Skip to footer

Adding AddEventListener() In Loop Only Works For Last Button

I get an json-array from dynamodb and is adding an addEventListener() to a button while traversing it. But only the last button responds to this. This has been asked before on SO a

Solution 1:

The main problem is that you redefine the HTML of adiv completely every time you iterate. This means that any event handler you had already bound to a child element of adiv is lost the moment you do adviv.innerHTML = .... Although you assign the same HTML plus some new one, you don't assign the event handlers that were previously defined. So they are lost.

Only the event handler you assign at the last iteration is not destroyed in this way.

Solution

A quick solution would be to first loop to create all the HTML, and then do a separate loop to assign the event handlers:

// First add all the new content:
var html = adiv.innerHTML;
for (var i = 0; i < array_length; ++i) {
    var obj = data.Items[i];

    html += "<div class='row'><div class='center-div six columns'>" + obj.Event + ", " + obj.Location + "</div></div>";
    html += "<div class='row'><div class='center-div six columns'>" + obj.Date + ", " + obj.Time + "</div></div>";
    html += "<div class='row'><div class='center-div six columns'><button id='yay_button_" + i + "' class='button-primary'>Deltag</button></div></div>";
}
adiv.innerHTML = html;

// Now bind the event handlers
// By using "let" instead of "var" the right value is retained
// in the handlers
for (let i = 0; i < array_length; ++i) {
    var elem = document.getElementById('yay_button_' + i);
    elem.addEventListener('click', function() {
        alert('id: ' + i);
    });
}

If your browser does not support ES2015 (for let), then you can use bind:

for (var i = 0; i < array_length; ++i) {
    var elem = document.getElementById('yay_button_' + i);
    elem.addEventListener('click', function(i) {
        alert('id: ' + i);
    }.bind(null, i));
}

Solution 2:

With kind advise from trincot I traverse the array twice. First to produce the html and then to apply the addEventListener(). The second time I surround the call to addEventListener() with a closure.

for (var i = 0; i < array_length; ++i) {
    var obj = data.Items[i];

    adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'>" + obj.Event + ", " + obj.Location + "</div></div>";
    adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'>" + obj.Date + ", " + obj.Time + "</div></div>";
    adiv.innerHTML = adiv.innerHTML + "<div class='row'><div class='center-div six columns'><button id='yay_button_" + i + "' class='button-primary'>Deltag</button></div></div>";

}

for (var i = 0; i < array_length; ++i) {
    var obj = data.Items[i];
    (function(j, event) {
        document.getElementById('yay_button_' + j).addEventListener('click', function() {
            alert('id: ' + j + ', ' + event);
        });
    }(i, obj.Event));
}

Post a Comment for "Adding AddEventListener() In Loop Only Works For Last Button"