ChangHun Lee
ChangHun Lee

Reputation: 65

I can't bind events to elements

const color = ['red', 'orange', 'yellow', 'green', 'blue', 'navy', 'purple'];
let a = [];
for (let i = 0; i < color.length; i++) {
  a[i] = document.createElement("input");
  a[i].type = 'button';
  a[i].id = 'b' + (i + 1);
  a[i].value = color[i];
  a[i].addEventListener('click', function() {
    alert('color');
  })
  document.body.appendChild(a[i]);
  document.body.innerHTML += "<br>"
  console.log(a[0].innerHTML);
}

It seems that the listener is not getting bound despite the addEventListener. What is the problem?

Upvotes: 2

Views: 329

Answers (2)

Abhishek Mani
Abhishek Mani

Reputation: 522

const color = ['red', 'orange', 'yellow', 'green', 'blue', 'navy', 'purple'];
let a = [];
for (let i = 0; i < color.length; i++) {
 a[i] = document.createElement("input");
 a[i].type = 'button';
 a[i].id = 'b' + (i + 1);
 a[i].value = color[i];
 document.body.appendChild(a[i]);
 document.body.innerHTML += "<br>"
 console.log(a[0].innerHTML);
 }
for (let i = 0; i < color.length; i++) {
   var el = document.getElementById("b" + (i + 1)) ;
   console.log(el)
el.addEventListener('click', function() {
   alert('color');
  })
}

https://jsfiddle.net/3zw0a1tx/

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370989

The problem is that, when concatenating with the innerHTML of a container (for example, with your document.body.innerHTML += "<br>"), the container will be emptied and then re-parsed with the new HTML string. If you previously attached a listener to an element in the container, that listener will not be in the HTML string, so it will not transfer over to the new element in the same position.

const div1 = document.querySelector('#somediv');
document.body.innerHTML += '';
const div2 = document.querySelector('#somediv');

console.log(div1 === div2);
// False, the container's contents were re-parsed, the new div is different!
<div id="somediv"></div>

Either append your br using the same appendChild method you're using for the a[i]:

const color = ['red', 'orange', 'yellow', 'green', 'blue', 'navy', 'purple'];
let a = [];
for (let i = 0; i < color.length; i++) {
  a[i] = document.createElement("input");
  a[i].type = 'button';
  a[i].id = 'b' + (i + 1);
  a[i].value = color[i];
  a[i].addEventListener('click', function() {
    alert('color');
  })
  document.body.appendChild(a[i]);
  document.body.appendChild(document.createElement('br'));
}

Or use insertAdjacentHTML instead, which can act similarly to .innerHTML +=, but unlike .innerHTML +=, does not re-create all elements in the container:

const color = ['red', 'orange', 'yellow', 'green', 'blue', 'navy', 'purple'];
let a = [];
for (let i = 0; i < color.length; i++) {
  a[i] = document.createElement("input");
  a[i].type = 'button';
  a[i].id = 'b' + (i + 1);
  a[i].value = color[i];
  a[i].addEventListener('click', function() {
    alert('color');
  })
  document.body.appendChild(a[i]);
  document.body.insertAdjacentHTML('beforeend', '<br>');
}

Upvotes: 5

Related Questions