Outline
My simple application takes text from a text box and calls an asp.net page method using AJAX. A list of users that partially match that text and their userID is returned. I wish to fill an existing DIV on the page with a DIV for each result, containing the users name. Each DIV then needs a click event to be bound to it that can call a javasacript method that can then have access to the key – the userID.
Code
function SearchButtonHandler(event) {
PageMethods.SearchInstructors($("#txtInstructorName").val(), SearchCallback);
return false;
}
The text to search is passed to the ajax call and the SearchCallback method receives a json array of objects containing an integer ‘UserID’ and a string ‘Fullname’.
This is the first way I did it, creating a ‘fake’ attribute on the DIV and having the click handler extract it:
function RowClicked() {
alert($(this).attr("userid"));
}
function SearchCallback(data) {
var collection = data.Result;
if (collection.length == 0) { //tell the user there were none
$("#resultlist").hide();
$("#nonefound").show();
} else {
$("#nonefound").hide();
$("#resultlist").empty();
//method 1 below
$.each(collection, function(index, item) {
$("#resultlist").append($("<div></div>").html(item.FullName).attr("userid", item.UserID).click(RowClicked));
});
$("#resultlist").show();
}
}
I don’t really like creating ‘fake’ attributes but came up with the following method:
$("#resultlist").append($("<div></div>").html(item.FullName).click(function() {
alert(item.UserID);
}));
So I have two alternatives that both work fine.
Question 1:
Is this second one less efficient? It seems to me that it needs to create a function for each DIV tag. Or is there another way to do it?
Question 2 (leading on from 1):
How is ‘item’ in scope when the click event is triggered? It clearly works, I just can’t see how that can be in scope!
You can use
.data()and$.data()to store custom attributes, like this:Then fetch it like this:
Or, a bit more efficient (not creating an extra jQuery object wrapper):
This stores the data in
$.cacheon the page, you already have the custom$.expandoattribute on the element (to store the click handler that’s also there), so you’re not adding anything invalid, you’re just using the expando data cache you already created.Note: The
$.expandovariable above isn’t accessible until jQuery 1.4+ when it was made “public”Edit, moving tangential part of the explanation here:
You can investigate the
$.cacheobject like this from an element (don’t use this in code!, it’s if you’re curious/want to poke):This is equivalent to
$.data(this),$.expandois a generated property when the page loads, looking something likejQuery1281004831434(jquery + timestamp on load) This is an attribute added to your element that’s a key, for example:jQuery1281004831434="4", in that case the cache object has a entry called4that stores your elements data and events…since this was already created for your click handler, you might as well use it, if avoiding another custom attribute is your goal.