Question

JavaScript's late binding is great. But how do I early bind when I want to?

I am using jQuery to add links with event handlers in a loop to a div. The variable 'aTag ' changes in the loop. When I click the links later, all links alert the same message, which is the last value of 'aTag'. How do I bind a different alert message to all links?

All links should alert with the value that 'aTag' had when the event handler was added, not when it was clicked.

for (aTag in tagList) {
  if (tagList.hasOwnProperty(aTag)) {
    nextTag = $('<a href="#"></a>');
    nextTag.text(aTag);
    nextTag.click(function() { alert(aTag); });
    $('#mydiv').append(nextTag);
    $('#mydiv').append(' ');
  }
}
Was it helpful?

Solution

You can pass data to the bind method:

nextTag.bind('click', {aTag: aTag}, function(event) {
    alert(event.data.aTag);
});

This will make a copy of aTag, so each event handler will have different values for it. Your use case is precisely the reason this parameter to bind exists.

Full code:

for (aTag in tagList) {
  if (tagList.hasOwnProperty(aTag)) {
    nextTag = $('<a href="#"></a>');
    nextTag.text(aTag);
    nextTag.bind('click', {aTag: aTag}, function(event) {
      alert(event.data.aTag);
    });
    $('#mydiv').append(nextTag);
    $('#mydiv').append(' ');
  }
}

OTHER TIPS

You can also make a wrapper function that takes the text to alert as a parameter, and returns the event handler

function makeAlertHandler(txt) {
  return function() { alert(txt); }
}

and replace

nextTag.click(function() { alert(aTag); });   

with

nextTag.click(makeAlertHandler(aTag));

You need to keep a copy of this variable, like this:

for (aTag in tagList) {
  if (tagList.hasOwnProperty(aTag)) {
    nextTag = $('<a href="#"></a>');
    nextTag.text(aTag);
    var laTag = aTag;
    nextTag.click(function() { alert(laTag); });
    $('#mydiv').append(nextTag);
    $('#mydiv').append(' ');
  }
}

The aTag variable is changing each time you loop, at the end of the loop it's left as the last item in the loop. However, each of the functions you created point at this same variable. Instead, you want a variable per, so make a local copy like I have above.

You can also shorten this down a lot with chaining, but I feel it clouds the point in this case, since the issue is scoping and references.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top