How to Append to Innerhtml Without Destroying Descendants' Event Listeners

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

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);
}
}

Element innerHTML getting rid of event listeners

It seems you misunderstood the problem. The problem is that you are overwriting innerHTML in order to insert contents.

Never use innerHTML to insert contents. It will remove all the internal data, like event listeners. This is what happens here.

If you want to prepend some HTML string, use insertAdjacentHTML:

var count = 0;function createOnclickFunction(number) {  return function() {    alert("This is button number " + number);  }}function addButton(data) {  var newbutton = "<button>Click me</button>" //creates string from data  var element = document.getElementById("mydiv");  element.insertAdjacentHTML('afterbegin', newbutton);  var children = element.children;  children[0].onclick = createOnclickFunction(count)  count++;}addButton();addButton();addButton();
<div id="mydiv"></div>

Manipulating innerHTML removes the event handler of a child element?

Yes, when you do:

document.body.innerHTML += '<br>'; 

You're really doing:

document.body.innerHTML = (document.body.innerHTML + '<br>'); 

So you're completely destroying and recreating all the content.

Event​Target​.add​Event​Listener() not working after innerHTML

When you concatenate to the innerHTML of an element, its contents are cleared, the existing HTML string is concatenated with the new string, and then the container's contents are re-calculated according to the new HTML string. ~~Listeners~~ Elements attached to elements previously in the container do not survive the serialization process - the children of the container after changing innerHTML are new.

Append a text node instead:

let label = document.createElement('label');let input = document.createElement('input');input.setAttribute('type', 'checkbox');input.addEventListener('change', () => alert('Change Detected'));
label.appendChild(input);document.body.appendChild(label);label.appendChild(document.createTextNode('Select Me!'));

How can I use innerHTML without delete the before innerHTML?

this can easily be done by building up your html string and then applying it with one call:

function cargar2(){
var h=1;//not sure why you have this
var html = "";

html += "<table>";

for (i=0;i<miArray.length;i++){
html += '<tr>';

for (j=0;j<miArray[i].length;j++){
html += '<td></td>' ;
}

html += '</tr>';
h++;
}

html += '</table>';

document.getElementById('tablaP').innerHTML = html;
}

EDIT: Fixed all the code formatting!

How to append text to a `div`?

Try this:

var div = document.getElementById('divID');

div.innerHTML += 'Extra stuff';

I am having issues with es6 classes and event listeners?

When you use thingHolder.innerHTML += html the old objects in the container are removed and recreated, but without their event listeners. So you are recreating them all every time you insert a new node that way.

The fact that the first button is the only one that works is because you are attaching an event only to the first element you encounter inside the parent (with querySelector), just after you removed all other events.

So the solution would be to create your elements with JS (or whatever is used in Babel) instead of using innerHTML.

How can I overwrite a portion of an element's text without affecting the rest of the element and any event listeners

Perhaps there's not a way to overwrite the text without nuking the event handler, but I did manage to fix my code so that it now at least adds the event handler back on after the minitoc.innerHTML = 'En Este Tema ' + remaining; line rewrites my paragraph.

Here's my updated function:

function localizeMiniTOC(){
const minitoc = document.querySelector('#MapCtrl + p');
const anchor = document.querySelector('#MapCtrl + p > a');
const text = minitoc.textContent;
if (text.includes('In\xa0this\xa0Topic') === true){
let html = minitoc.innerHTML;
linkStart = html.indexOf('<a');
remaining = html.substring(linkStart,html.length);
if (anchor.id.includes('MTHotSpot') === true){
minitoc.innerHTML = 'En Este Tema ' + remaining;
minitoc.addEventListener('click', function(e){
if (e.target.tagName === 'SPAN' && e.target.className==="MTText"){
TextPopup(anchor.id);
}
});
}
}
}

Notice that I had an error in my original attempted workaround to add the event listener back in. In this incorrect code, I had neglected to call the function properly in the second parameter:

minitoc.addEventListener('click', TextPopup('MTHotSpot46267'));

Here's the fixed code for that (taken from my updated function):

minitoc.addEventListener('click', function(e){
if (e.target.tagName === 'SPAN' && e.target.className==="MTText"){
TextPopup(anchor.id);
}

This results in the event listener getting added to the paragraph and then it was just a matter of making sure I was clicking on the span tag before running the TextPopup function.

In this pic, you can see the added event:
Inspector showing the added event



Related Topics



Leave a reply



Submit