scottysseus
scottysseus

Reputation: 2020

Adding click listeners to list items in loop

I have the following code:

    // Iterate through each of the children
    for(j = 0; j < len; j++) {
        var entry = sortedArray[j];

        // Each entryLI is a child of nameOL <ol> element
        var entryLI = document.createElement("li"); 

        // Each entryLI should have a unique click listener
        entryLI.addEventListener("click", function(event) {entry.onListItemClick()});

        // Set the text of the <li> to the name of the entry
        var nameNode = document.createTextNode(entry.entryName);
        entryLI.appendChild(nameNode);

        // Append the entry list item to the ordered list
        nameOL.appendChild(entryLI); 
    }

I am trying to, within this loop, give each list item an event listener that handles click events. However, for some reason, clicking on any of the list items calls the event listener of the last item in the list.

Can anyone explain to me why this is?

I am coming to JavaScript from completely different languages and I am struggling with prototype-based classes.

Upvotes: 1

Views: 150

Answers (2)

rajuGT
rajuGT

Reputation: 6404

It is because of the below line

entryLI.addEventListener("click", function(event) {entry.onListItemClick()});

is bounded to variable entry and not to its value. So what ever is assigned or value changed throughout all loop, the value at the last iteration is holded in entry variable and every event handler function will access that variable gets the last value.


Solution: use immediate function as Kenney suggested in this Q thread or check this answer it is less ambiguous.

Upvotes: 1

Kenney
Kenney

Reputation: 9093

The entry variable gets overwritten on each loop. One way to circumvent this is:

for(j = 0; j < len; j++) {

    (function(entry){

       ....

    })(sortedArray[j])

}

This IIF (immediately-invoked-function) scopes the entry variable separately for each iteration.

Upvotes: 3

Related Questions