I'm building a list of buttons and I want each one to trigger the addForm() function with the current members[member].id.
But it happens that only the last button will fire the event.
I know it has something to do with closures and as you can see I have adapted the function to use this pattern.
What am I doing wrong?
function displayConnections(connections) {
/*(...)*/
for (var member in members) {
connectionsDiv.innerHTML += "<p>" + members[member].firstName + " " + members[member].lastName
+ " ID: " + members[member].id;
btn = document.createElement("input");
btn.setAttribute("type","button");
btn.setAttribute("value","Send Message");
btn.setAttribute("id",members[member].id);
btn.onclick = function (id) {
return function () {
addForm(id);
};
}(members[member].id);
connectionsDiv.appendChild(btn);
}
}
Thanks.
First, remember you are not writing C# or Java. The
for (var ... in ...)
structure does not iterate a collection. You should always checkhasOwnProperty
to see if the property name belongs to the object itself:Then check to make sure that the property value is an object and not a function etc.
Second, your variable
btn
is lacking avar
declaration. You are creating a global variable calledbtn
, not a variable local to your function.Next, you have a typo mistake in your original code. Your original code actually is interpreted this way (thanks to JavaScript's auto-semicolon-insertion feature!):
In order to run your program in your original style, you need to bracket the function definition:
jsFiddle.
In this block of code:
You have the syntax wrong - it should be:
What this does is automatically invoke a new anonymous closure, which has a locally bound copy of
members[member].id
in itsid
parameter, which itself then returns a closure which is what's actually bound tobtn.onclick
.The automatic invokation only happens if you put the outer parenthesis around the closure declaration.
Well, instead of those workaround you can also use:
which worked for me and should work for you as well.