Search code examples
javascriptinnerhtmleventhandler

Only the last element I added using innerHTML keeps its event handlers, why?


I am trying to make a script that injects interactable object information in a list of the markup page. Whenever I try to add an onclick event on a div, it works fine, however whenever I try to add more within a for loop, it does not work the way I intended.

I took a look of what is going on using breakpoints in the webpage debugger, and I see that the problem is that it seems to delete the event on the previous div before adding to the next div. In the end, the only event remaining is the last div after the loop exits.

I want to keep these events on all my divs, not just the last one... what seems to be the problem here?

var objects = ['Tom', 'Sauna', 'Traum'];

for (var i = 0; i < objects.length; i++){
    document.getElementById('list').innerHTML += "<div class='item' id='"+ i +"'>" + objects[i] + "</div>";
    document.getElementById(i).addEventListener("mouseup", function() {
        Select(this);
    });
}

function Select(char) {
    console.log(char);
}
div.item {
    border: 1px solid black;
    padding: 4px;
    margin: 4px;
}
<div id="list"></div>

enter image description here


Solution

  • When you change innerHTML browser reconstructs the element's contents, throwing away all event handlers attached. Use DOM methods instead:

        for (let i = 0; i < objects.length; i++){
            var block = document.createElement('div');
            block.setAttribute('id', i);
            document.getElementById('list').appendChild( block );
            block.addEventListener("mouseup", function() {
                Select(this);
            });
        }
    

    UPD: alternatively use a insertAdjacentHTML method instead of redefining innerHTML:

    document.getElementById('list').insertAdjacentHTML(
        'beforeend', "<div id='"+ i +"'>" + i + "</div>");