Sunday, March 22, 2009

jQuery: Leveraging Element Data

A common task when dealing with UI is displaying data.  When it comes to HTML and persisting data, things can get pretty interesting and ugly.  jQuery makes attaching data to HTML elements very simple.  Using the data method, you are able associate data with an element, given a key (this allows for multiple pieces of data to be associated to a single element).  Mix this with jQuery’s powerful selectors, we are able to create some interesting user experiences.  I’ve put together a sample in which we retrieve a series of Users and available Security Roles, from a .NET Web Service.  The UI allows a user to drag various users into their appropriate groups.

$(msg.d).each(function() {
$("<div></div>").addClass("item").text(this.Username).appendTo("#userList").data("__jsonData", this);
});
$(".user .item").draggable({ revert: true });

Once we get our response back from the GetUsers call, we iterate through each of the items in the response and create the HTML elements.  In doing so we additionally associate the JSON object with the new html element, using the key of “__jsonData”.  Finally, we make all the newly created elements draggable.


$(msg.d).each(function() {
var newContainer = $("<div></div>").addClass("container role").appendTo("body").data("__jsonData", this);
$("<div></div>").addClass("role-title").text(this.Name).appendTo(newContainer);
});
$(".role").droppable({
drop: function(event, ui) {
if (ui.draggable.hasClass("item")) {
var dropData = ui.draggable.data("__jsonData");
$("<div></div>").addClass("item").appendTo($(this).removeClass("over")).text(dropData.Username).data("__jsonData", dropData);
}
},
over: function(event, ui) { if (ui.draggable.hasClass("item")) $(this).addClass("over"); },
out: function(event, ui) { if (ui.draggable.hasClass("item")) $(this).removeClass("over"); }
});
$(".role").draggable({ handle: ".role-title" });
$(".user").draggable({ handle: ".title" });

Next, we make our call to the GetRoles web service.  Once, the call returns we again create the new HTML elements.  Each container will invoked the droppable.  We will feed it several parameters, mainly to signify if the draggable element is of the “item” type.  Since we’ve made the containers draggable, the drop target needs to know whether or not is a container or an item.



$("#report").click(function() {
var reportString = "";

$(".role").each(function() {
reportString += $(this).data("__jsonData").Name + "\r\n-------------\r\n";
$(this).children(".item").each(function() {
var itemData = $(this).data("__jsonData");
reportString += itemData.FirstName + " " + itemData.LastName + " (" + itemData.Username + ")\r\n";
});
reportString += "\r\n";
});

alert(reportString);
});

Finally, we want to summarize the data, once the user is done putting their users into the appropriate groups.  I’ve simply added a click handler to the “report” button.  This simple compiles a string of all roles and the users that were defined for the role.  Here we can see that we are putting the summary together based on attributes that are not displayed in the UI anywhere.  We are yanking this information out of the JSON object, that we stored in the jQuery data for the given elements.  We could easily add the User data to the Role.Users array and ship them off to an update web service.


So, as you can see, the jQuery element data allows you to create a pretty flexible UI without having to do anything like create hidden fields and/or complicate your HTML, simply to support tracking UI and data as one unit.


Download Source

No comments:

Post a Comment