Rey Bango

Web developer, honey badger

jQuery JavaScript Templates Tutorial: Nesting Templates

In my last post, I presented an intro to how to create a template using the new jQuery Template plugin being developed by the Microsoft Ajax Core team. In this tutorial, I’ll show you how to nest templates to have great control over your layout.

The nesting of a template within another template is a pretty valuable feature as it lets you create a modular structure for your layout. Instead of having to create one enormous template to cover every scenario, you can break the layout apart into individual templates and piece them together. Let’s start by defining some data:

       var clientData = [
	        { name: "Rey Bango", age: 42, id: 1, phone: [ "954-600-1234", "954-355-5555" ] },
	        { name: "Mark Goldberg", age: 51, id: 2, phone: ["954-600-1234", "954-355-5555"] },
	        { name: "Jen Statford", age: "25", id: 3, phone: ["954-600-1234", "954-355-5555"] }
        ];

What I’d like to do is to render the basic information like the name and age in one template and then render the phone numbers for each client in a different template.

Like I showed in my previous post, we first create a template for our layout:

<script id="clientTemplate" type="text/html">
	<p><a href="clients/${id}">${name} - Age: ${age}</a></p>
</script>

This will display the name and age as a hyperlink included within paragraph tags. Next, we create a new template that will be used to render the phone numbers for each client”

<script id="phoneTemplate" type="text/html">
	<ul>{{each phone}}<li>${$value}</li>{{/each}}</ul>
</script>

Lastly, we’re going to include the call to “phoneTemplate” in our main template using the “tmpl” tag. This tag is used by the plugin to identify templates and parse them accordingly. Here’s what the call would look like:

{{tmpl($data) "#phoneTemplate"}}

and we’re going to include it into the main template:

<script id="clientTemplate" type="text/html">
	<p><a href="clients/${id}">${name} - Age: ${age}</a></p>
	{{tmpl($data) "#phoneTemplate"}}
</script>

This will generate the following results:

There are a couple of key things to understand here. First, let’s look at the following:

{{tmpl($data) "#phoneTemplate"}}

The variable “$data” contains the data for the current record being parsed. We’re passing it to the nested template so that we can work with that record. Let’s move onto the nested template:

<script id="phoneTemplate" type="text/html">
	<ul>{{each phone}}<li>${$value}</li>{{/each}}</ul>
</script>

Now that the current record has been passed to it, we can access the attribute name, in this case “phone”, and loop through each phone record using the ‘{{each}}‘ plugin template tag. Think of it as similar to jQuery’s $.each() method or a JavaScript “for” loop. The code will loop through each phone record creating a new list item for each one and then return to the main template to get the next main record.

Here’s the whole code for you to work with:

<!DOCTYPE html>
<html lang="en">
<head> 
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
  <meta name="robots" content="noindex" /> 
  <title>Template Test</title> 
  <script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
  <script src="jquery.tmpl.js" type="text/javascript"></script>  
  <script type="text/javascript">
  $(document).ready(function() {

        var clientData = [
	        { name: "Rey Bango", age: 42, id: 1, phone: [ "954-600-1234", "954-355-5555" ] },
	        { name: "Mark Goldberg", age: 51, id: 2, phone: ["617-777-1234", "617-222-3333"] },
	        { name: "Jen Statford", age: "25", id: 3, phone: ["608-555-5647", "608-645-8855"] }
        ];

        $("#clientTemplate").tmpl(clientData).appendTo("div");

});
  </script>

<script id="clientTemplate" type="text/html">
	<p><a href="clients/${id}">${name} - Age: ${age}</a></p>
	{{tmpl($data) "#phoneTemplate"}}
</script>

<script id="phoneTemplate" type="text/html">
	<ul>{{each phone}}<li>${$value}</li>{{/each}}</ul>
</script>
  
</head> 
 
<body> 

<div></div>

</body> 
</html> 

Category: AJAX, JavaScript, jQuery

Tagged:

28 Responses

  1. Bill Mild says:

    Rey,

    I’m fascinated by what is happening here between jquery and Microsoft, but my off-the-cuff reaction is: Does anyone ever need to bind from client data? Usually, data is on a db server. How about a full-service example, starting from a db server, then getting to client and rendering? Then, enabling CRUD functionality?

    Cheers,
    Bill

  2. @Bill,

    The data can be retreived using jQuery.ajax method, so you can use the received data object instead of the hardcoded example.

    jQuery(function(){
    jQuery.ajax({
    url: ‘/someJSONService’,
    success: function(data){
    $(‘#clientTemplate’).tmpl(data).appendTo(‘div’);
    }
    });
    });

    You can also send data with ajax and jQuery has some good documentation on how to achieve this. How you set up CRUD services however is kinda outside of scope of this article/jQuery plugin. I suggest setting up RESTfull services and using jQuery.ajax to post requests, there are many articles on the net on this very topic, just do a search ;)

  3. Awesome. Any reason why this isn’t yet documented on the main page? (Or if it is, I didn’t see it.)

  4. COol. Rey – a bit OT – any chance you can add email notifications for new comments?

  5. Jatin Nanda says:

    thanks for the example and very timely indeed. Your original post had me thinking about this and I happened to come across this post :-)

    I have been playing with 3 levels of nesting (and kinda got it working) by nesting {{each}}. Is there a nicer way of doing this? I guess what I am trying to say is can we not add a {{tmpl($data) “#someTemplate”}} for each level of nesting?

    Thanks

    J

  6. […] jQuery JavaScript Templates Tutorial: Nesting Templates – Rey Bango continues his series looking at templating in jQuery with a look at using nested templates to provide multi-level templating. […]

  7. […] jQuery JavaScript Templates Tutorial: Nesting Templates (Rey Bango) […]

  8. Anton Visser says:

    Ray, I’m loving these templates, they are going to make my life so much easier. Do you know if the creators are talking about any kind of form elements to add to the templates? For instance, if I wanted to add a row to a table, and one of the cells of the table was a select, it would require some fun coding right now, to create the select and then select the item you want selected by default.

    • Yasmine says:

      Great work Ray!
      @Anton Visser: Your suggestion is exactly what I’m trying to do, did you start working on this template? I couldn’t figure out how to choose the default option (selected)

  9. […] jQuery JavaScript Templates Tutorial: Nesting Templates […]

  10. kyle says:

    You can use multiple sets of data (multiple JSON objects) as sources for the nested templates.

    For example, I needed to for each user, display a drop down that allows the choice of several dynamic options. I chose to make them a separate JSON object, for sake of bytes transferred to the server.

    So…

    var clientData = [
    { name: “Rey Bango”, age: 42, id: 1, phone: [ “954-600-1234″, “954-355-5555″ ] },
    { name: “Mark Goldberg”, age: 51, id: 2, phone: [“617-777-1234″, “617-222-3333″] },
    { name: “Jen Statford”, age: “25”, id: 3, phone: [“608-555-5647″, “608-645-8855″] }
    ];

    var dropDownOptions = [
    { text: “Text 1″, value: 1 },
    { text: “Text 2″, value: 2 },
    { text: “Text 3″, value: 3 }
    ];

    $(“#clientTemplate”).tmpl(clientData).appendTo(“div”);

    ——————————-

    Looks normal, right? Then, in the template, instead of referencing the data object as {{tmpl($data) “#ddTemplate”}}, you reference it as {{tmpl(dropDownOptions) “#ddTemplate”}}

    ——————————-

    So, for example, I needed to display a drop down list with dynamic options in it…

    <select>
    {{tmpl(dropDownOptions) “#ddTemplate”}}
    </select>

    ——————————-

    and my template definition is:

    <option value=’${value}>${text}</option>

    Thanks for the article! Very helpful

  11. jan hrabowski says:

    Alternatively you can do the same example with these 2 templates (without {{each}})

    ${name} – Age: ${age}
    {{tmpl(($data).phone) “#phoneTemplate2″}}

    ${$item.data}

  12. […] information about using a template: Dancing with Data: Introducing jQuery Templates 1: First Steps jQuery JavaScript Templates Tutorial: Nesting Templates – Rey Bango Not Using jQuery JavaScript Templates? You’re Really Missing Out. – Rey Bango […]

  13. ian says:

    thanks. this helped me a lot! I followed your instructions modified for my project thinking “ugh this is never going to work” but got it on the first try. cheers!

  14. David says:

    Hi,

    I realize this has been posted a while ago, but I’ll try my luck at asking a question.

    I don’t get the “clients/${1}” part in the href. What purpose does it serve?

    Thanks in advance! :)

    David.

  15. Kieran says:

    Hey great post.
    I have a question about going deeper into each json object.
    Take:
    [
    {“Name”:”Home”,”NiceUrl”:”/home/”,”Children”:null},
    {“Name”:”MX-8″,”NiceUrl”:”/mx-8/”,”Children”:null,{“Name”:”Quiz”,”NiceUrl”:”/quiz/”,”Children”:
    [{“Name”:”Thank you”,”NiceUrl”:”/quiz/thank-you/”,”Children”:
    [{“Name”:”Can’t get here”,”NiceUrl”:”/URL/”,”Children”:null}]}]}}
    ]

    Using your example above i can easily get to “Quiz” and its child “Thankyou” but is there a way to recursively call a second template?

    I have tried setting the type of the second template to “text/x-jquery-tmpl” and calling a 3rd template but the data being passed is

  16. Alex Shyba says:

    Thanks Rey, finding this blog post was a real time saver!

  17. Eslam Foula says:

    Wonderful post.

    I just have a question….
    I need to call a span, div or td “whatever” with their id or class to add a function to them from another js file.

    For example “related to your code above”:

    – If the code of the template is like that,

    {{each phone}}${$value}{{/each}}

    I need now to call the div by it’s id “example” in another js file with a basic jquery code like the following:

    $(document).ready(function () {
    $(“#example”).hide();
    });

    But I find that nothing change, and I don’t know why ????????????!!!!!!!!!

    ————–
    Thanks.

  18. Eslam Foula says:

    Sorry there’s something going wrong.

    I meant the code of the template looks like the following:

    {{each phone}}${$value}{{/each}}

  19. Eslam Foula says:

    mmm you closed typing tags in your comment forms.

    Anyway I meant looks like the following:

    (script id=”phoneTemplate” type=”text/html”)
    (ul){{each phone}}(li)${$value}(/li){{/each}} (/ul)
    (/script)

  20. Eslam Foula says:

    (script id=”phoneTemplate” type=”text/html”)
    (ul id=”example”){{each phone}}(li)${$value}(/li){{/each}} (/ul)
    (/script)

  21. Hi Ray,
    I know this is an older post, but I stumbled upon it just today when searching for nested template information.

    The problem is that the information I need to show (in your example: the field w/ phonenumbers) in my case is a collection of objects itself from which I need to show only one or two fields.

    for example
    phone: [{phone-home: “954-600-1234″, phone-work: “954-355-5555″, phone-mobile:” …”}, {…} ]

    How do I get to the value of ‘phone-home’?

    I tried notation like {{each phone}}${$value.phone-home}{{/each}}

    and

    {{each phone}}${$value[“phone-home”]}{{/each}}

    and various others. But to no avail.

    Any help is greatly appreciated.

    regards,
    Peter.

Learn JavaScript!

What to Read to Get Up to Speed in JavaScript.

The best books & blogs for learning JavaScript development. Broken down by experience levels!


My BIG LIST of JavaScript, CSS & HTML Development Tools, Libraries, Projects, and Books.

Constantly updated with the latest and greatest tools. Check it out!

Categories

Rey Bango is Stephen Fry proof thanks to caching by WP Super Cache