Using jQuery Templates to Bind to JSON data Blog post

jQuery

Note that this is an old post and there may well be better alternatives now, such as KnockoutJS , AngularJS, jsRenderHandlebarsJS etc.

Note it still works, though - If you want to pop straight to the demo then look here!

Original Post from 2011

In 2010 Microsoft raised a few developer eyebrows when it turned out they were contributing ideas and code to the jQuery Project. One of these ideas turned out to be a plug-in that made the task of binding data to repeatable segments of HTML much simpler and cleaner. Microsoft called this idea jQuery Templates. The guys at jQuery liked the idea and so, around the middle of last year, jQuery Templates were added to the library as official jQuery plug-ins. Note the old repo can now be found on GitHub at https://github.com/BorisMoore/jquery-tmpl

In this post I'll show you how you can use jQuery Templates to easily bind to JSON data returned from a simple Ajax request. For the example we will be using the Flickr API, since it is a free, fast and reliable API that plays nicely with JSONP requests (just think of JSONP as way of dealing with cross-domain Ajax requests without running into cross-domain scripting problems).

So What are Templates For?

The jQuery documentation describe templates thus:

"A template contains markup with binding expressions. The template is applied to data objects or arrays, and rendered into the HTML DOM."

If you are familiar with .NET then this might remind you of something - Databinding. This is no surprise since both the ideas come from Microsoft. But even if you don't know .NET, you will recognise that it is a common occurence to take a stream of data and have to transform that into HTML. In the past you might have done this by concatenating strings to make HTML - a rather messy and error-bound affair, complicated by having to escape quotes and the like.

For instance, you may recognise ugly jQuery code like the following for creating an HTML unordered list by iterating over a collection of JSON objects:

var html = "";
$.each(data.items, function(key, val)
{
    html += "<li>" + val.title + "</li>";
});

It works, but is fiddly even for such a simple construct. When you start generating more complex HTML it soon becomes an unmaintainable mess. This is where templates come in - they solve this problem by separating your mark-up from the data. The idea behind templates is simple - you create your HTML as a template that contains 'variables' that 'bind' to the data you are consuming. It's probably easiest to see this in example of what a template looks like:

<script id="flickrTemplate" type="text/x-jquery-tmpl">
    <li>${title}</li>
</script>

As you can see, a template is really just a JavaScript script block (with a unique ID) that contains a fragment of HTML. The HTML, in turn, can contain placeholder variables like ${title} that are replaced by the actual values in the JSON data when the template is bound (i.e. the data and the template are combined to produce actual HTML).

A Full Example using Flickr API

So, putting this all together, I'll show you very quickly how you can use templates to bind to JSON returned from the Flickr API (this data will consist of the latest photographs from the Flickr timeline, which will contain titles, URLs and other metadata). Just bare in mind that jQuery Templates are still in beta and thus subject to change (which might break this example at some point in the future!).

OK. First, we will use jQuery Ajax to query the API with a JSONP request that returns the photographs and descriptions. The JSON we expect to get back looks like this:

jsonFlickrFeed({
        "title": "Uploads from everyone",
        "link": "http://www.flickr.com/photos/",
        "description": "",
        "modified": "2011-03-01T10:49:41Z",
        "generator": "http://www.flickr.com/",
        "items": [
       {
            "title": "20110226__7AT0068.jpg",
            "link": "http://www.flickr.com/photos/alf_69/5488083463/",
            "media": {"m":"http://farm6.static.flickr.com/5057/5488083463_2e67cda7bf_m.jpg"},
            "date_taken": "2011-02-26T20:56:37-08:00",
            "published": "2011-03-01T10:49:41Z",
            "author": "[email protected] (alf_69)",
            "author_id": "[email protected]",
            "tags": "candeloris mimmas80thbirthdayparty"
       },
       {
            "title": "Rockies09_1931 Lake McDonald 3.03pm",
            "link": "http://www.flickr.com/photos/ausken/5488083475/",
            "media": {"m":"http://farm6.static.flickr.com/5013/5488083475_4f46fe6b1d_m.jpg"},
            "date_taken": "2009-07-31T15:03:47-08:00",
            "published": "2011-03-01T10:49:41Z",
            "author": "[email protected] (AusKen)",
            "author_id": "[email protected]",
            "tags": ""
       },
..... etc

So, now we know what data to expect we can create a template to render each of the items returned. For this example we will create a simple list that contains the title, image and a link to the original image on Flickr. We create our template and place it in a script block as below:

<!-- This is the template -->
<script id="flickrTemplate" type="text/x-jquery-tmpl">
    <li>
        <h2>${title}</h2>
        <div><a href="${link}"><img src="${media.m}" alt="${title}" /></a></div>
    </li>
</script>

(Notice how we can reference nested JSON items by using a period - so that to get the media items with an "m" attribute we just use ${media.m}).

We then make our Ajax request to Flickr, specifying we are using a JSONP callback. This query should return the photo feed as JSON into the variable called data. We then take the items within the data object and pass it to the template as data.items (identifying the template by it's ID of 'flickrTemplate'). This 'binds' the JSON to the template, so that each variable in the template is replaced by it's equivalent value:

    $(document).ready(function()
    {
        $.ajax({
            url: "http://api.flickr.com/services/feeds/photos_public.gne",
            data: "format=json",
            jsonp: "jsoncallback",
            dataType: "jsonp",
            success: function(data)
            {
                $("#flickrTemplate").tmpl(data.items).appendTo("#placeholder");
            }
        });
    });

Finally we use the appendTo() function to add the rendered template items to an HTML UL identified uniquely as 'placeholder'. This effectively adds the HTML list to the DOM.

<ul id="placeholder"></ul>

Demonstration

You can view a demonstration of this in action here. Just view the page source to see the entire code. Hopefully you will agree templates are a neat and elegant way of binding data.


Just fill in the form and click Submit. But note all comments are moderated, so spare the viagra spam!

Tip: You can use Markdown syntax within comments.