Templates are cool and useful as a way of easily generating dynamic content in a page. But they are one-way only: You can bind the data to the template for display, but there is no support to let the user update the data and automatically update the underlying JavaScript objects. That's where data linking comes in, implemented in the jQuery Data Link plug-in developed by Microsoft's ASP.NET and jQuery teams. Data linking provides a way to link a property of one object to a property of another object. Once linked, updating the linked property on either object automatically updates the property on the other object. The most common use for data linking is to link the properties of a JavaScript object to form fields on a page.

This data linking behavior is more commonly called binding, but since there is already a jQuery bind method, the team decided to call it data linking instead. The jQuery bind method binds events to objects, not data.

If the names of the properties of the two objects are the same, such as if a form's input elements have name attributes with values that are the same as the object you want to link to, data linking can automatically set up all the links for you. Or you can specify a mapping between the two objects' properties, whatever works best for you. The plug-in also supports converters, letting you define a function that automatically performs conversion or formatting when you need to modify the property value as it is updated on the other object. There is a lot of flexibility built into the Data Link plug-in.

The plug-in consists of two primary methods: link and unlink. As their names imply, the link method creates a link between object properties and unlink breaks the link. You won't often have to use unlink, because the plug-in cleans up a link when either its target or source object is a DOM element that is going out of memory, such as when its parent object is cleared.

If you've done a lot of data binding with ASP.NET and other parts of the .NET Framework, this might all sound pretty familiar. And it kind of works the same, to a limit. But there is one huge difference, at least in the current development version of the Data Link plug-in. The difference is that the linking isn't activated immediately once you call the link method when binding an object to a form or input elements. Instead, it is activated by the DOM change event, and that event is triggered when the input control loses the focus and its contents have been changed since it last had the focus. Most of the time this won't be a huge issue, but you will need to make allowance for this behavior in how you use and code data links.

How all this works in the final release is anybody's guess at this point though. It will take some time for Microsoft's proposal to gain the acceptance of the jQuery community and get approval, and until then the plug-in is a moving target.

Exploring the Plug-in

To explore data linking, I adapted the Contacts.html sample page from the reference sample used by the Data Link team to demonstrate how data linking works at any given point. When you first view this page in a browser, you'll see the page shown in Figure 1.

Figure 1: Contacts.html sample web page

It is a simple application for maintaining a set of contacts, letting you add new contacts and sort them. You can add as many contacts and phone numbers as you like. The one kind of weird feature is the age bar in the right column: its width corresponds to the age of the person, presumably so that you can quickly and easily find your oldest and youngest contacts!

The Save contacts button displays the current data contained in the contacts variable, as JSON. Figure 2 shows the data displayed on the page immediately after loading the page, before making any changes to the contact data. This provides a handy way to see the current state of the data.

Figure 2: Data displayed on Contacts.html page

The HTML in the body of the page is fairly simple, shown below. The table will display the contacts and let the user make changes. The results <pre> element displays the JSON data when you click the Save contacts button.

<h1>My Contacts - Data Link</h1>
<table class="contacts"></table>
<input type="button" id="insert" value="Insert new contact" />
<input type="button" id="sort" value="Sort by Last Name" />
<input type="button" id="save" value="Save contacts" />
<pre id="results"></pre>

The page uses a fairly complex jQuery template, shown below, to dynamically add the contacts to the page. What's most interesting here is how the template uses the {{each}} template tag to loop through and display all the contacts and each contact's phone numbers. Notice that the loop for the phone numbers is nested within that of the contacts, letting the page easily display unlimited contacts and unlimited phone numbers for each contact. This would be quite a chore to code in raw, unaided JavaScript!

<script id="contactTemplate" type="text/x-jquery-tmpl">
    <tr>
    <th>&nbsp;</th>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Phone Numbers</th>
    <th>Age</th>
    </tr>
    {{each contacts}}
    <tr class="contact">
    <td>
    <a href="#" class="contact-remove">remove</a><br/>
    <a href="#" class="contact-reset">reset</a><br/>
    </td>
    <td>
    <input name="firstName" class="contact" type="text"
        value="${firstName}" />
    </td>
    <td><input name="lastName" class="contact" type="text"
        value="${lastName}" /></td>
    <td>
    <table class="phones">
    <tr>
    <th>&nbsp;</th>
    <th>Type</th>
    <th>Number</th>
    </tr>
    {{each phones}}
    <tr class="phone">
    <td><a href="#" class="phone-remove">remove</td>
    <td><input class="phone phone-type" name="type"
        type="text" value="${type}" /></td>
    <td><input class="phone phone-number" name="number"
        type="text" value="${number}" /></td>
    </tr>
    {{/each}}
    </table>
    <a href="#" class="newphone">add new phone</a>
    </td>
    <td>
    <input type="text" class="agebar" name="age"
        value="${age}" />
    </td>
    </tr>
    {{/each}}
</script>

Most of what is interesting in the sample page is in the Contacts.js code file, referenced by the Contacts.html page. There is a lot there, and it is worth taking the time to explore, but here you'll learn about the data linking features. The code file starts off by creating the contacts object and initializes it with two contacts, each with two phone numbers, as in the following code. As you add, remove, and change contact information, the page stores the data in this object, which it links to the input elements on the page.

var contacts = [
    {firstName:"Dave", lastName:"Reed", age:32, phones: [
        { type: "Mobile", number: "(555) 121-2121" },
        { type: "Home", number: "(555) 123-4567"}]
    },
    {firstName:"John", lastName:"Doe", age:87, phones: [
        { type: "Mobile", number: "(555) 444-2222" },
        { type: "Home", number: "(555) 999-1212"}]
    }
];

Starting at line 54 in the code file, the code binds the contactTemplate to the contacts object and appends the result to the contacts table in the HTML source. This creates a table row for each contact, as well as nested tables for the phone numbers. Then it uses the jQuery each method to loop through each of the contact rows in the table, using the "tr.contact" selector to the jQuery function. Here is where the code calls the link method to bind all the input elements within the row to the contact properties with the same name. Notice that you don't have to do this for each field, as long as names match or you include a mapping. For the age, it also sets the width of the age textbox to the width in pixels equal to the person's age. It also triggers the changeField event to the value of the contact's age, which is what causes the link to be created for that field.

$("#contactTemplate").tmpl(
    { contacts: contacts }).appendTo(".contacts");
// bind inputs to the data items
$("tr.contact").each(function (i) {
    var contact = contacts[i];
    $("input.contact", this).link(contact);
    $('.agebar', this).link(contact, {
        age: {
                convertBack: function (value, source, target) {
                        $(target).width(value + "px");
                }
        }
    });
    $(contact).trigger("changeField", ["age",contact.age]);

There is more code after the above code that sets up the click event function for the contact-remove and contact-reset links. The latter retrieves the original values of the first and last names and restores them if there have been changes.

Starting at line 81 is the code that links the contact's phone type and number to the input elements, as shown below. Other code here (not shown below) sets up the click event functions for the phone-remove and newphone links.

$("tr.phone", this).each(function (i) {
    var phone = contact.phones[i];
    $(this).link(phone, {
        type: "type",
        number: {
                name: "number",
                convert: "phone"
        }
    });

The above code sets up a mapping of the phone number fields so that it can use a converter to format the phone number, called phone. The code defines this converter starting at line 15, shown below. This code strips out the common non-numeric characters from the phone number and normalizes the number to the (907) 555-1212 form used in the United States, Canada, and some other countries.

$.extend($.convertFn, {
    phone: function (value) {
        // and parens
        value = (parseInt(value.replace(/[\(\)\- ]/g, ""),
                10) || 0).toString();
        value = "0000000000" + value;
        value = value.substr(value.length - 10);
        value = "(" + value.substr(0, 3) + ") " +
                value.substr(3, 3) + "-" + value.substr(6);
        return value;
    },
    ...
});

It takes a little work to set up and use data linking in a page, but it is far simpler than it would be in plain JavaScript code. Each iteration of the plug-in as it progresses toward final release makes things a little bit easier, so there's a good chance that you'll need to write even less code in the final release version.

You can download the Data Link plug-in and sample application here.

This article is adapted from courseware I wrote for AppDev.

Don Kiely ( donkiely@computer.org), MVP, MCSD, is a senior technology consultant, building custom applications and providing business and technology consulting services. His development work involves SQL Server, Visual Basic, C#, ASP.NET, and Microsoft Office.