0

i have data which i loop and build dynamically HTML label elements to each element, i attach addEventListener with click event and function that takes the current value.
but when i click the elements that are created only the last element from the initial array is passed as an argument to the addEventListener function.
in the below example when clicking on foo1 or foo2 the value is always of foo3
i expect that each onclick hold its own key data.
so when i click foo1 it will give foo1
and when i click foo2 it will give foo2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="UTF-8">
    <title>Title</title>

    <style>

</style>
<script>
var data = {
    "foo1" : "aaa",
    "foo2" : "bbb",
    "foo3" : "ccc"
}
var popolateDS = function() {
    self = this;
    for(var key in data) {
        if (data.hasOwnProperty(key)) {
         var label = document.createElement('label');
             label.innerHTML = key;
             label.id = "lbl_"+key;
             label.addEventListener("click", () =>{
                    self.dsOnClick(key);
         }, false);
         document.getElementById("container2").appendChild(label);
         var br = document.createElement('br');
         document.getElementById("container2").appendChild(br);
        }
    }
}

var dsOnClick = function(key)  {
    alert(key);
}

</script>
</head>
<body>
<div id="container2">
</div>

<button onclick="popolateDS()">click</button>




</body>
</html>
user63898
  • 29,839
  • 85
  • 272
  • 514
  • `for(var key in data)` => `for (let key in data)` –  Jul 13 '21 at 09:59
  • found this answer to be the right one : https://stackoverflow.com/questions/19586137/addeventlistener-using-for-loop-and-passing-values – user63898 Jul 13 '21 at 10:09

1 Answers1

0

It is a scoping problem. You can replace your var with a let

When you use var, in the end all your event listeners on the different label elements point to the very same value. let is block scoped, and every iteration value is different. So when you click on foo1 you are referring the correct value.

If you still want to use a var you will have to pass in parameters into your function. That way they are a different value and are not scoped to the key variable outside.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="UTF-8">
    <title>Title</title>

    <style>

</style>
<script>
var data = {
    "foo1" : "aaa",
    "foo2" : "bbb",
    "foo3" : "ccc"
}
var popolateDS = function() {
    self = this;
    for(var key in data) {
         var label = document.createElement('label');
             label.innerHTML = key;
             label.id = "lbl_"+key;
            
             label.addEventListener("click",                    (a) => { 
                     self.dsOnClick(a);
         }, false);
         document.getElementById("container2").appendChild(label);
         var br = document.createElement('br');
         document.getElementById("container2").appendChild(br);
    }
}

var dsOnClick = function(key)  {
    alert(key);
}

</script>
</head>
<body>
<div id="container2">
</div>

<button onclick="popolateDS()">click</button>




</body>
</html>
Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
  • This is a code-only answer of a dupe. edit: no longer-code only but still a one-line answer of a dupe –  Jul 13 '21 at 10:00
  • if i want to use var still without using let – user63898 Jul 13 '21 at 10:05
  • Yes, a little tedious as far as I know, but you can do that by passing in a variable to your event handler and creating a separate scope for your function. Check answer. – Tushar Shahi Jul 13 '21 at 10:38