1

Why doesn't the code below print it's corresponding value when clicked?

Instead, it prints 5?

var recipeDiv = document.createElement("div");
var recipeUL = document.createElement("ul");
for (var i = 0; i < 5; ++i) {
    var listNode = document.createElement("li");
    listNode.innerHTML = i;
    listNode.onclick = function() { alert(i); }
    recipeUL.appendChild(listNode);
}
recipeDiv.appendChild(recipeUL);
addNodeToDOM(document.body, recipeDiv, 'recipe');

function addNodeToDOM(element, node, id) {
    var div = document.createElement('div');
    div.id = id;
    div.appendChild(node);
    element.appendChild(div);
}

I was able to reproduce the bug here: jsfiddle

But basically, I'm not sure if this is the convention for adding elements correctly to the DOM. If so, how come whenever I click on the list elements, it doesn't show

Shaunak D
  • 20,588
  • 10
  • 46
  • 79
user3288944
  • 81
  • 2
  • 11

3 Answers3

2

When, onclick handler executes, the value of i will always show 5 as the for loop ends at 5th iteration,

Use this.innerHTML,

listNode.onclick = function() { alert(this.innerHTML); }

Updated Fiddle

Shaunak D
  • 20,588
  • 10
  • 46
  • 79
  • Hi, thanks. I understand now. What if I was parsing through a JSON file and assigning onclick() based off of an array position i? How would I do that? – user3288944 May 21 '15 at 06:11
  • Iterate through the JSON array using a loop, assign the values, rest of the code would be almost similar to above. – Shaunak D May 21 '15 at 06:14
  • Thinking about it... would storing it into an array be the only option? – user3288944 May 21 '15 at 06:15
  • Array would be a better option. There are many tutorials/answers available which could guide you. – Shaunak D May 21 '15 at 06:16
1

Another simple solution is to have a wrapper function.

for (var i = 0; i < 5; ++i) {
    (function(i){

      var listNode = document.createElement("li");
      listNode.innerHTML = i;
      listNode.onclick = function() { alert(i); }
      recipeUL.appendChild(listNode);

    })(i);
}

This way you can always rely on the iterator variable i.

Zee
  • 8,420
  • 5
  • 36
  • 58
0

This is where closure concept plays its role. Try modifying listNode.onclick = function() { alert(i); } line of code with this:

listNode.onclick = (function(index) { return function(){alert(index);} })(i);

I have updated your fiddle.. FIDDLE

Rakesh_Kumar
  • 1,442
  • 1
  • 14
  • 30