1

I have some code to add some HTML and attach a listener to them, strangely when I add some more things to the page the eventlisteners for previously added elements don't work.

JS:

(function() {
    document.body.innerHTML = "<div class=\"container\"></div>";

    document.querySelector(".container").innerHTML += "<p class=\"red\">RED</p>";                             
    document.querySelector(".red").addEventListener("click", function() {
        console.log("red");
    });

    document.querySelector(".container").innerHTML += "<p class=\"purple\">PURPLE</p>";                           
    document.querySelector(".purple").addEventListener("click", function() {
        console.log("purple");
    });

    document.querySelector(".container").innerHTML += "<p class=\"blue\">BLUE</p>";                           
    document.querySelector(".blue").addEventListener("click", function() {
        console.log("blue");
    });
})();
aznafro
  • 15
  • 3

3 Answers3

2

Modifying innerHTML will destroy and rebuild all descendant elements of the container. Event handlers bound to any of the destroyed elements are lost in the process and need to be reattached if required. Please, use .insertAdjacentHTML method.

0

The issue is, innerHTML rebuild the full HTML, thus all the descendant element's events are lost. You can use Element.insertAdjacentHTML() instead:

The insertAdjacentHTML() method parses the specified text as HTML or XML and inserts the resulting nodes into the DOM tree at a specified position. It does not reparse the element it is being used on, and thus it does not corrupt the existing elements inside that element. This avoids the extra step of serialization, making it much faster than direct innerHTML manipulation.

(function() {
    document.body.innerHTML = "<div class=\"container\"></div>";

    document.querySelector(".container").innerHTML += "<p class=\"red\">RED</p>";                             
    document.querySelector(".red").addEventListener("click", function() {
        console.log("red");
    });

    document.querySelector(".container").insertAdjacentHTML("beforeend", "<p class=\"purple\">PURPLE</p>");                           
    document.querySelector(".purple").addEventListener("click", function() {
        console.log("purple");
    });

    document.querySelector(".container").insertAdjacentHTML("beforeend", "<p class=\"blue\">BLUE</p>");                           
    document.querySelector(".blue").addEventListener("click", function() {
        console.log("blue");
    });
})();
Mamun
  • 66,969
  • 9
  • 47
  • 59
0

When you adjust innerHTML, the whole element will be rebuilt (and any attached listeners will be lost in the process), so you have to add your listeners after the adjustments:

(function() {
    document.body.innerHTML = "<div class=\"container\"></div>";

    document.querySelector(".container").innerHTML += "<p class=\"red\">RED</p>";
    document.querySelector(".container").innerHTML += "<p class=\"blue\">BLUE</p>";    
    document.querySelector(".container").innerHTML += "<p class=\"purple\">PURPLE</p>";                           

    document.querySelector(".red").addEventListener("click", function() {
        console.log("red");
    });

    document.querySelector(".purple").addEventListener("click", function() {
        console.log("purple");
    });

    document.querySelector(".blue").addEventListener("click", function() {
        console.log("blue");
    });
})();
Patric
  • 1,489
  • 13
  • 28