2

I have several elements that get eventlisteners added so I can capture event data. It works great but I need each to have a unique ID. If you look at the snippet below, you can see that the ID will always last value.

var buttons = document.getElementsByClassName('class');

for (var i = 0; i < buttons.length; i++) {
  var id = i + 1;
  
  buttons[i].onclick = function() {
    buttonClicked(id);
  }
}

function buttonClicked(id) {
  document.getElementById('output').innerHTML = 'Button ID: ' + id;
}
<button class="class">Button 1</button>
<button class="class">Button 2</button>

<hr>

<div id="output"></div>

I am aware that you could put the onclick event in the HTML, but I need the event data. It also needs to have the onclick in as a function() as I have it. Is there a way I could somehow freeze the id variable value for the function?

Jack
  • 1,893
  • 1
  • 11
  • 28
  • `var` does not use block scope. `const` would be best since the value doesn't change, but `let` would also work. – Patrick Roberts Dec 28 '19 at 22:08
  • @PatrickRoberts, thanks! Never would have been able to find that. Seemed like this question would have been answered before. Can't delete it now since there is an answer though. – Jack Dec 28 '19 at 22:11

1 Answers1

3

It's because of the closure around the looping variable i and the id variable. Change the variable declarationd to let i = 0 and let id = i + 1 to create a unique scope for them upon each loop iteration.

var buttons = document.getElementsByClassName('class');

for (let i = 0; i < buttons.length; i++) {
  let id = i + 1;
  
  buttons[i].onclick = function() {
    buttonClicked(id);
  }
}

function buttonClicked(id) {
  document.getElementById('output').innerHTML = 'Button ID: ' + id;
}
<button class="class">Button 1</button>
<button class="class">Button 2</button>

<hr>

<div id="output"></div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71