innerHTML only takes effect once, and dynamically generated elements

Asked

Viewed 263 times

1

I am doing a javascript experiment that when clicking on a certain element with a certain class we will add a new element with the same class, whenever clicking should appear a new element.

var my_divs = document.getElementsByClassName('my-div');
for (var i = 0; i < my_divs.length; i++) {
    my_divs[i].addEventListener('click', function() {
       var next_id = my_divs.length + 1; 
       document.body.innerHTML += '<div id="div' +next_id+ '" class="my-div"></div>';
       //console.log(next_id);
    });
}
.my-div {
  width:20px;
  height:20px;
}
.my-div:nth-child(odd) {
  background-color:red;
}
.my-div:nth-child(even) {
  background-color:blue;
}
<div id="div1" class="my-div">

</div>

As you can see, it works, but only once. I even understand that the click that appears dynamically does not do anything because the event was not associated with the new div. But still, why does the first click only take effect once? And how would I get what I want? Whenever I click any (.my_div), dynamically generated or not appearing another?

1 answer

1


The problem is that += is the same as document.body.innerHTML = document.body.innerHTML + resto, ie re-write all the HTML and so breaks the event headphones.

To make it work for any element (created after or not) you need a delegator, in which case you can use .appendChild() or rewrite all the HTML as you were doing. I prefer to use .appendChild(), using += in the body.innerHTML is violent and can spoil code in other parts of the DOM.

Example using delegation:

var ids = 2;
var minhaClasse = 'my-div';
window.addEventListener('click', function(e) {
    var el = e.target;
    if (!el.classList.contains(minhaClasse)) return;
    var div = document.createElement('div');
    div.classList.add(minhaClasse);
	div.id = ids++;
    document.body.appendChild(div);
});
.my-div {
    margin: 20px;
    height: 20px;
    width: 20px;
    background-color: #ddf;
}
<div id="div1" class="my-div"></div>

jsFiddle: https://jsfiddle.net/5pdvxp9q/

Another more local way would be like this:

function addDiv() {
    var div = document.createElement('div');
    div.classList.add(minhaClasse);
    div.id = ids++;
    div.addEventListener('click', addDiv);
    document.body.appendChild(div);
}
document.querySelector('.my-div').addEventListener('click', addDiv);

jsFiddle: https://jsfiddle.net/5pdvxp9q/2/

  • 1

    Thanks @Sergio. That’s right... I accept in a few minutes

  • Instead of rewriting everything, just add clear.

  • Haa you just add the event to the window and only then specify the element for sure. It’s the same as $(window).on('click', '.my-div', function() { ... }) right?

  • I just noticed a little mistake in your... maybe I should edit the second div, the first to be generated comes with id=0, should come with id=2

  • @Exact Miguel, with jQuery would be the delegation code. I added more info to the answer.

  • Thank you. Clarified

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.