Is it possible to append to innerHTML without destroying descendants' event listeners?

Related searches

In the following example code, I attach an onclick event handler to the span containing the text "foo". The handler is an anonymous function that pops up an alert().

However, if I assign to the parent node's innerHTML, this onclick event handler gets destroyed - clicking "foo" fails to pop up the alert box.

Is this fixable?

<html>
 <head>
 <script type="text/javascript">

  function start () {
    myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    mydiv = document.getElementById("mydiv");
    mydiv.innerHTML += "bar";
  }

 </script>
 </head>

 <body onload="start()">
   <div id="mydiv" style="border: solid red 2px">
     <span id="myspan">foo</span>
   </div>
 </body>

</html>

Unfortunately, assignment to innerHTML causes the destruction of all child elements, even if you're trying to append. If you want to preserve child nodes (and their event handlers), you'll need to use DOM functions:

function start() {
    var myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    var mydiv = document.getElementById("mydiv");
    mydiv.appendChild(document.createTextNode("bar"));
}

Edit: Bob's solution, from the comments. Post your answer, Bob! Get credit for it. :-)

function start() {
    var myspan = document.getElementById("myspan");
    myspan.onclick = function() { alert ("hi"); };

    var mydiv = document.getElementById("mydiv");
    var newcontent = document.createElement('div');
    newcontent.innerHTML = "bar";

    while (newcontent.firstChild) {
        mydiv.appendChild(newcontent.firstChild);
    }
}

Is it possible to append to innerHTML without destroying , Is it possible to append to innerHTML without destroying descendants' event listeners? append innerhtml jquery insertadjacenthtml javascript append div to� We can add elements to a DOM element by creating an element and appending it. (Let’s pretend we have an exisiting div element to work with) Using innerHTML is cleaner, especially when we start

Using .insertAdjacentHTML() preserves event listeners, and is supported by all major browsers. It's a simple one-line replacement for .innerHTML.

var html_to_insert = "<p>New paragraph</p>";

// with .innerHTML, destroys event listeners
document.getElementById('mydiv').innerHTML += html_to_insert;

// with .insertAdjacentHTML, preserves event listeners
document.getElementById('mydiv').insertAdjacentHTML('beforeend', html_to_insert);

The 'beforeend' argument specifies where in the element to insert the HTML content. Options are 'beforebegin', 'afterbegin', 'beforeend', and 'afterend'. Their corresponding locations are:

<!-- beforebegin -->
<div id="mydiv">
  <!-- afterbegin -->
  <p>Existing content in #mydiv</p>
  <!-- beforeend -->
</div>
<!-- afterend -->

Is it possible to append to innerHTML without destroying , Is it possible to append to innerHTML without destroying descendants' parent node's innerHTML , this onclick event handler gets destroyed� "Is it possible to append to innerHTML without destroying descendants' event listeners?". Reading through the answers to that question you will find ways around this using native methods like .insertAdjacentHTML() which will work once adapted to your case. There is no need to step out of the D3 universe, though, as this can easily be done in a chained statement like the following:

Now, it is 2012, and jQuery has append and prepend functions that do exactly this, add content without effecting current content. Very useful.

Tutorial :Is it possible to append to innerHTML without destroying , Is it possible to append to innerHTML without destroying descendants' event the parent node's innerHTML , this onclick event handler gets destroyed - clicking � innerHTML is essentially the element's content as a string. Be warned, though: 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.

As a slight (but related) asside, if you use a javascript library such as jquery (v1.3) to do your dom manipulation you can make use of live events whereby you set up a handler like:

 $("#myspan").live("click", function(){
  alert('hi');
});

and it will be applied to that selector at all times during any kind of jquery manipulation. For live events see: docs.jquery.com/events/live for jquery manipulation see: docs.jquery.com/manipulation

Tutorial :Is it possible to append to innerHTML without destroying descendants' event listeners? Anonymous Unknown 20:40 � Unknown� Hi everyone, If I have to make a lot of changes to the content of my page, something like adding (div + a + h1 + p + text node) X 10 times, what is better, innerHTML (variable with markup + select element to update + update content) or DOM Manipulation Methods (create every node + append nodes one by one + select element to update + append new content). I know that innerHTML is less code, some

I created my markup to insert as a string since it's less code and easier to read than working with the fancy dom stuff.

Then I made it innerHTML of a temporary element just so I could take the one and only child of that element and attach to the body.

var html = '<div>';
html += 'Hello div!';
html += '</div>';

var tempElement = document.createElement('div');
tempElement.innerHTML = html;
document.getElementsByTagName('body')[0].appendChild(tempElement.firstChild);

Is it possible to append to innerHTML without destroying descendants' event listeners? mike; 2009-02-27 17:43; 9. In the following example code, I attach an� Someone who wants to depend on the behavior can use .empty().append(html) explicitly and get consistent cross-browser behavior. We could lobby for Microsoft to make the behavior consistent with the other browsers in IE10 though.

I dynamically create a checkbox that has an EventListener. Unfortunately the EventListener doesn't work if I change the text of the checkbox-label with innerHTML: let label = document.

Adding to the DOM n times takes n times more time than adding to the DOM a single time. (:P) This is the logic I'm personally following. In consequence, when it is about to create, for instance, a SELECT element, and add to it several options, I prefer to add up all options at once using innerHTML than using a createElement call n times.

Someone who wants to depend on the behavior can use .empty().append(html) explicitly and get consistent cross-browser behavior. We could lobby for Microsoft to make the behavior consistent with the other browsers in IE10 though.

Comments
  • This question is related to the 'appending new fields to a form erases user input' problem. The selected answer fixes both of these problems very nicely.
  • Event delegation can be used to tackle this problem.
  • Is there a substitute that can append an arbitrary blob of HTML?
  • newcontent= document.createElement('div'); newcontent.innerHTML= arbitrary_blob; while (newcontent.firstChild) mydiv.appendChild(newcontent.firstChild);
  • Nice, Bob! If you post that as a well-formatted answer, I'll select it.
  • @bobince — I've updated my answer with your technique, since you haven't posted it yet yourself. If you create your own answer, go ahead and roll mine back. :-)
  • Oh, one last thing, you'll want "var myspan", "var newcontent" etc. to avoid accidentally spilling globals.
  • You saved my day!
  • Best solution. Thank you!
  • .insertAdjacentHTML has been around since IE4