This is the 8th article in our "Bring the clouds together: Azure + Bing Maps" series. You can find a preview of live demonstration on http://sqlazurebingmap.cloudapp.net/. For a list of articles in the series, please refer to http://blogs.msdn.com/b/windows-azure-support/archive/2010/08/11/bring-the-clouds-together-azure-bing-maps.aspx.

Introduction

Our previous post described how to work with Bing Maps in a rich HTML application. A map provides a modern representation of geography related data. It also allows you to do a lot of work that you formerly did using lists. You can, for example, popup a form when user clicks a pushpin, to collect data about that particular location.

But we have to admit lists (or similar representations) are still very useful, even when working with geography data. For example, when planning a trip across the global, a list can potentially help you to quickly find a particular data without navigating around the map. Additionally, some users may simply prefer to work with lists.

This post introduces how to use jQuery Templates to easily create a list to represent structured data in a rich HTML application. You will see how it helps you to reduce efforts compared to a traditional solution, such as creating DOM elements in JavaScript. We assume the audiences have basic knowledge of HTML 4, JavaScript, CSS, and jQuery. No HTML 5 knowledge is used.

Traditional solutions to display lists

There're two solutions to display lists in a HTML web application: Server side solution and client side solution.

Most web developers using Microsoft technologies know how to display lists with a server side solution, using ASP.NET server controls like ListView. Those server controls provide a rich programming model with rich data binding support. You can define a template for a single data item, associate the template with a list of data source, and the template will be automatically applied to all data items. ASP.NET MVC developers can also take advantage of foreach loop and html helpers to display a list without too much efforts.

But as more and more web applications move towards client driven (especially consumer oriented web applications), developers have to begin to investigate JavaScript. Traditionally, Microsoft doesn't provide a JavaScript framework that is as easy to use as server side framework such as ASP.NET. So developers have the following options:

  • Use ASP.NET UpdatePanel (or partial view in MVC) to create the list on the server side. This simulates AJAX behavior, but since every request requires a round trip to the server, performance will be impacted.
  • Write JavaScript code: Work with DOM, create lots of elements, combine various strings, and so on... This takes a lot of efforts. See the below appendix for an idea.
  • Use a third party JavaScript framework. Since currently there's no standard framework, developers may have a hard time to figure out which framework to use for which project.

Appendix: Create a list using JavaScript without jQuery Templates.

 $(datasource).each(function ()
{
DisplayItem(this);
});

function DisplayItem(item)
{
var li = $('<li/>');
var divPlace = $('<div/>');
divPlace.append(item.Place);
divPlace.addClass('LeftColumn');
li.append(divPlace);
// Latitude
li.append('<div>' + item.Latitude + '</div>');
// Longitude
li.append('<div>' + item.Longitude + '</div>');
var divTime = $('<div/>');
var textTime = $('<input/>');
textTime[0].type = 'text';

textTime[0].value = $.datepicker.formatDate('yy-mm-dd', item.Time);
textTime[0].readOnly = true;
textTime.datepicker({ onSelect: DateChanged, dateFormat: 'yy-mm-dd' });
divTime.append(textTime);
li.append(divTime);
var deleteButton = $('<input type="button" value="Delete"/>');
deleteButton.click(DeleteItem);
var divDelete = $('<div/>');
divDelete.append(deleteButton);
li.append(divDelete);
li.append('<input type="hidden" value="' + item.ID + '"/>');
li.click(SelectItem);
$('#LocationList').append(li);
}

Introduce jQuery Templates

To avoid the problems in traditional client driven web application development, Microsoft and jQuery had a joint investment. The result is jQuery Templates, which is currently in Beta. If you have experience with WPF/Silverlight DataTemplate, you can roughly think jQuery Templates plays the same role as Silverlight DataTemplate. If you have experience in ASP.NET, you can roughly think it is a ListView control, except everything is done on the client side. We will not describe what jQuery Templates is with further text, instead, let's see it in action.

First, link to the jQuery Templates script. You can download the script from http://plugins.jquery.com/project/jquerytemplate, or simply use AJAX CDN.

    <script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>

Now suppose we have a list of objects. Each object has the following properties:

PartitionKey, RowKey, Place, Latitude, Longitude, Time

Create a template

To display the data, first create a template. A template is also a script. But it's not JavaScript. The type is text/x-jquery-tmpl.

    <script id="travelTemplate" type="text/x-jquery-tmpl">

    <li>

        <div class="ItemContainer" onclick="SelectItem(this)">

            <div class="PlaceDiv">${Place}</div>

            <div>Location: ${Latitude}, ${Longitude}</div>

            <div>Time: <input type="text" class="DatePicker" value="${formatDate(Time)}" readonly/></div>

            <input type="button" value="Delete" onclick="DeleteItem(this)"/>

            <input type="hidden" value="${PartitionKey}"/>

            <input type="hidden" value="${RowKey}"/>

        </div>

    </li>

    </script>

As you can see, most of the scripts are plain old html. You can design the template using any tool you like, such as Expression Web.

You can see tokens like "${Place}". This means when the template is applied, the value of the Place property on the data source object will replace the place holder. Note if you download the source code (which will be available soon), you will find we're actually using "${Value.Place}", because our data source object has a property named Value, which in turn has a property named Place. To avoid confusion, we choose to simply list "${Place}" in the above code snip.

Template only controls the structure of data representation. It doesn't control the style directly. But everything you know about CSS also apply to templates.

Apply the template

Now that the template has been created, we can apply it to a list, such as a <ul>. To do so, first clear all items in the ul. Currently jQuery Templates does not take care of that for you (unlike Silverlight DataTemplate). Then find the template element, invoke the tmpl method, pass the data source as the parameter, and append the result to the ul.

    // Remove old data.

    $('#TravelList').children().remove();

    // Apply the jQuery template to the ul.

    $('#travelTemplate').tmpl(items).appendTo('#TravelList');

Here the variable items is a collection of data source object, which is returned from our WCF Data Services. We'll cover how to invoke WCF Data Services from a HTML client in the next post.

For Silverlight developers, please note there's no ObservableCollection in jQuery Templates as you can find in Silverlight. So if the source collection is modified, you need to invoke the above two lines of code again, to reapply the template.

Additional tweaks to the template

Sometimes you may want to perform additional tasks on the data. For example, format a date. jQuery Templates allows you to invoke functions in the templates. You can roughly think it acts as the same role as Silverlight binding converter. In the above template, we have seen the TextBox associated with the Time property invoke the formatDate function:

<input type="text" class="DatePicker" value="${formatDate(Time)}" readonly/>

function formatDate(date) {

    return $.datepicker.formatDate('yy-mm-dd', date);

}

If a simple function is not sufficient, you can always iterate through the generated DOM fields, and do anything you like. For example, to associate a jQuery UI datepicker with the TextBox, we give the TextBox in template a style class, and search for all generated TextBoxes with this style class later:

    $.each($('.DatePicker'), function (index, item) {

        $(item).datepicker({ onSelect: DateChanged, dateFormat: 'yy-mm-dd' });

    });

Now let's see a screenshot of the result (Note it may be a bit different from what you see in the current version of live demonstration. When writing those blog posts, we're also refining our code and design, to create a better coding guideline and user experience. The live demonstration will be updated in the future):

Conclusion

This post introduced jQuery Templates, and how it helps to reduce efforts when displaying structured data in a rich HTML application. It focused on client side only. The next post will bring the client and the cloud together. We will introduce how to accessing WCF Data Services from a rich HTML client.