Composition with jQuery Templates: Why and How
JavaScript, jQuery, UI By Dave Ward. Updated November 11, 2010I doubt anyone was happier than I was to see that support for composite template rendering was added to jQuery Templates during the interim between the first community proposal and its recent release. If you’re a regular reader, you might remember that I personally lobbied for that functionality back in May, based on how I’ve used jTemplates’ similar #include feature.
Since then, a common question I’ve received amounts to: “Great, but why?”
I think that’s natural, because template composition is one of those things that can seem obscure until you put it to work for the first time. From that point onward, you’ll begin to see the structure of your client-side templates in a different light. Simplifying your templates into smaller logical parts and then combining those parts to create the desired end result is a powerful approach. It’s terrific for making large templates more approachable and maintainable over the lifetime of an application.
In this post, I want to show you an example of a scenario that template composition is well suited to, a couple ways that jQuery Templates’ {{tmpl}} feature can be used to simplify that scenario, and a bonus advantage that the composition approach provides even after the template has been rendered.
An example scenario: The invoice
Imagine that you need to display an invoice for a company that resells taxable items and also sells services. Ideally, the invoice line items for those separate “types” should be displayed with different markup. To explore a simple example of that, let’s create a template to render the invoice for a fictional web development company.
Whether retrieved from a server-side endpoint or embedded in the page during initial rendering, the underlying data for that invoice might be structured something like this:
var invoice = { invoiceItems: [ { type: 'item', part: '99Designs', description: '99 Designs Logo', price: 450.00, qty: 1 }, { type: 'service', service: 'Web development and testing', price: 25000.00 }, { type: 'item', part: 'LinodeMonthly', description: 'Monthly site hosting', price: 40.00, qty: 12 } ] };
Following from that data structure, our goal for the invoice’s markup might look something like this:
<table> <tr> <td>99Designs</td> <td>99 Designs Logo</td> <td>$450.00</td> <td>1</td> </tr> <tr> <td colspan="2">Web development and testing</td> <td colspan="2">$25,000.00</td> </tr> <tr> <td>LinodeMonthly</td> <td>Monthly hosting at Linode</td> <td>$40.00</td> <td>12</td> </tr> </table>
Notice that the markup for service and item rows is structurally different, to better represent the underlying data. When that’s desirable, composing sub-templates is the way to go. As we’ll see next, the alternative is unappealing.
The old fashioned way
The key to our goal of rendering different markup for services and items is to render different template code depending on the line item’s type property.
Of course, it’s possible to achieve that without using template composition. The {{if}} template tag allows you to concoct just about any conditional rendering scheme that you can image. For example:
<script id="invoiceTemplate" type="x-jquery-tmpl"> <table class="invoice"> {{each invoiceItems}} {{if type == 'service'}} <tr class="service"> <td colspan="2">${service}</td> <td colspan="2">${price}</td> </tr> {{else type == 'item'}} <tr class="item"> <td>${item}</td> <td>${description}</td> <td>${price}</td> <td>${qty}</td> </tr> {{/if}} {{/each}} </table> </script>
That works, but it’s a mess.
Even with only two types of items, the template is already fairly difficult to read and digest. Just imagine if there were a dozen item types instead of only two. Bundling all the templates together would quickly become a maintenance nightmare.
Wouldn’t it be nice if we could separate the row templates and define them individually? The {{tmpl}} template tag allows us to do just that.
Reorganizing the template for composition
First, we need to separate the template into a container and individual row templates for each line item type. The container will be rendered once for every invoice, and the row templates as dictated by the underlying data.
In this case, the container template will simply begin and end our <table>. In a real-world template, this is where you might also include a <thead> with column headings.
<script id="invoiceTemplate" type="x-jquery-tmpl"> <table class="invoice"> <!-- Composition magic goes here! --> </table> </script>
The row templates are straightforward, extracted from the combined template we looked at in the last section:
<script id="serviceRowTemplate" type="x-jquery-tmpl"> <tr class="service"> <td colspan="2">${service}</td> <td colspan="2">${price}</td> </tr> </script> <script id="itemRowTemplate" type="x-jquery-tmpl"> <tr class="item"> <td>${item}</td> <td>${description}</td> <td>${price}</td> <td>${qty}</td> </tr> </script>
Note that the templates have IDs that correspond to the type they’re designed to render. That will come in handy a bit later.
Template composition with jQuery Templates
Now, it’s finally time to add that composition magic to the container template. jQuery Templates has a special template tag which provides for rendering and composing nested templates: {{tmpl}}.
The {{tmpl}} tag has several usages (documentation), but the one I want to focus on is the one that accepts a selector as its template parameter. When a selector is specified, jQuery Templates locates the indicated template, renders it, and then replaces the {{tmpl}} token with that rendered markup.
The {{tmpl}} command also accepts a parameter specifying what data the sub-template should be rendered with. Including the template selector, the command will look like this: {{tmpl(dataItem) "#TemplateID"}}.
Putting that all together, this container template will use each item’s type to render the item with the appropriate row template:
<script id="invoiceTemplate" type="x-jquery-tmpl"> <table class="invoice"> {{each invoiceItems}} {{if type == 'service'}} {{tmpl($value) '#serviceRowTemplate'}} {{else type == 'item'}} {{tmpl($value) '#itemRowTemplate'}} {{/if}} {{/each}} </table> </script>
If you aren’t familiar with {{each}} and its $value pseudo variable, all you need to know is that it contains the current iteration’s data item. It’s the same value that you would normally capture as the second parameter to an $.each() callback. In fact, {{each}} can also be used in that fashion instead:
<script id="invoiceTemplate" type="x-jquery-tmpl"> <table class="invoice"> {{each(i, item) invoiceItems}} {{if type == 'service'}} {{tmpl(item) '#serviceRowTemplate'}} {{else type == 'item'}} {{tmpl(item) '#itemRowTemplate'}} {{/if}} {{/each}} </table> </script>
I prefer using the pseudo variable since it’s more concise, but both are equivalent.
For now, we’re still stuck with the {{if}} to determine which row template to render, but getting the row templates out of that conditional block has cleaned things up quite a bit. Don’t worry if the conditional strikes you as a distasteful remnant of the original approach. We’ll fix that soon.
Rendering the composite template
Having defined the container template and its sub-templates, using jQuery Templates to render the entire group is just as easy as rendering a single template. Assuming the same invoice variable as seen before:
$('#invoiceTemplate').tmpl(invoice).appendTo('body');
As far as we know at the time we render the container, nothing has changed (and that’s part of the point), yet the refactored template is going to be quite a bit easier to understand and maintain.
Unconditional rendering love
Now that the templates are separated, things are a lot cleaner than before. However, that remnant {{if}} block is still a bit irritating. If you end up with more than just a couple item types, the conditional will require ongoing maintenance and cruft up the template badly.
Instead of that explicit testing and branching to pick the right template, we can clean things up by automatically searching for a row template that matches our naming convention of typeRowTemplate. To do that, we just need to build a JavaScript function that takes a type parameter and returns the appropriate selector string:
function get_invoiceRowTemplateName(type) { // Return a template selector that matches our // convention of <type>RowTemplate. return '#' + type + 'RowTemplate'; }
Updating the container template to use our new function completely eliminates that {{if}} block:
<script id="invoiceTemplate" type="x-jquery-tmpl"> <table class="invoice"> {{each lineItems}} {{tmpl($value) get_invoiceRowTemplateName(type)}} {{/each}} </table> </script>
Now, adapting to new item types is as simple as creating an appropriately named template. Convention over configuration, as they say.
Bonus: Rendering additional line items
Cleaning up the template is a good enough reason alone to use template composition, but the benefits extend beyond the initial rendering process. A nice side-effect of the compositional approach is that it’s easy to render additional rows even after the template has been rendered.
It’s easy to imagine that we might need to let users add new items to our invoice after it has been displayed. Assuming the invoice is already rendered, adding a matching row to it is as easy as this:
var newItem = { type: 'service', service: 'Service with a smile', price: 0.00 }; // Determine which template should be used to render the new item. var tmpl = get_invoiceRowTemplateName(newItem.type); // Render that template, using the new item as data, // and append that new row to the end of the existing invoice table. $(tmpl).tmpl(newItem).appendTo('#table.invoice');
That’s cleaner, easier, and faster than the common alternatives of cloning an existing row, building the HTML manually, or completely re-rendering the entire table with updated data.
Perhaps more importantly, it centralizes your presentation code. When changes only need to be made once, in a single location, you are guaranteed to see less bugs over time.
Conclusion
I’ve been using this compositional approach with jTemplates for a couple years now, and I cannot overstate how helpful it is when you’re working on real-world apps with large, complex client-side templates. I do hope you’ll give it a try in your own projects, because I know you won’t be disappointed.
Kudos to everyone who worked on jQuery Templates and helped {{tmpl}} see its way into the first release. I think it’s an excellent implementation of the feature – certainly easier to use and understand than jTemplates’ #include.
An important piece of the puzzle that’s still missing at this point is a technique for storing these composite template groups in an external file and loading them asynchronously, as with single templates in my last post. Unfortunately, the simplistic approach in my previous post doesn’t work with composite templates. However it’s still very easily doable. I’ll cover that next, so stay tuned.
What do you think? Are you using template composition already? If not, have I managed to entice you to give it a try?
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.



Nice post Dave, I’d been looking for a good explanation on how to use the {{tmpl}} syntax as it’s something that I’m investigating for a project.
The only thing I can’t seem to work out with using {{tmpl}} is whether you can lazy-load the different templates.
The reason that I’m thinking of those is if you’re building a mobile UI and you want to limit the amount of data sent to the client. I’m limiting this by putting the templates into separate files and only loading them as-required.
Have you see how (if at all) you can use {{tmpl}} with lazy-loaded templates?
You can remotely load these composite groups of templates, similar to what I described in my last post (but a bit different). My next post will cover doing that with this same invoice example, moving the templates to a separate file.
Sweet, I’ll be hanging out for that one!
Bravo, this is very useful!
Thanks Dave!
Hi Dave,
Which would you recommend, jQuery Templates or jTemplates? I’ve been using jTemplates for a while now and quite like them but I’m open to new ideas especially with Microsoft and jQuery working together on Templates.
Thanks
Jon
For sites using jQuery, I recommend jQuery Templates going forward.
Its inclusion in jQuery 1.5 will make it hard to justify adding the overhead of downloading another templating library when we’ll already be getting jQuery Templates for free with jQuery.
jQuery Templates has already seen great traction in the community too, even in the short time its been visible. That makes a big difference when people run into difficulties and search for examples or post on help sites.
Plus, its popularity is leading to interesting complementary projects. I’ve already seen server-side rendering implementations for .NET, PHP, and node.js so far. I expect we’ll see its templates be just as easily rendered on the client or server-side soon, which will be great for SEO and accessibility.
Whatever happened to “Its inclusion in jQuery 1.5″
I’ve read loads of posts on this but cannot find anything stating why it didn’t actually end up in the library… unless I’m missing something.
I don’t know the whole story, but one reason is that the jQuery Templates plugin is still in beta and I believe there’s still another beta coming before the final release. I can see how it wouldn’t make sense to roll it into core until its API was sure to be stable.
Dave, thank you for explaining this feature. It definitely adds more flexibility to templates. Especially with your example of getting the name dynamically.
you mentioned the pseudo-variable $value that you used here:
{{each lineItems}}
{{tmpl($value) get_invoiceRowTemplateName(type)}}
{{/each}}
but where did that type variable come from? Is that a pseudo as well or is that part of each lineItems?
It’s a property on the objects in the lineItems array, assuming the same sample data shown up in the first section. As {{each}} loops through the items, each item’s properties are available inside the {{each}} without any extra qualifier.
$value.type would be the same thing, if that makes more sense or seems more intuitive.
Thats really sweet. I will be definately be using this approach.
WOW…
WOW…
Great explanation and sample code, can’t wait to do it myself.
when you add the jQuery templates with LINQ and ASP.NET. WOW…
AWSOME man, thanks for the lift….
Carlos
This seems very similar to how XSLT is used to transform XML into XHTML. Replace XML with JSON, and XSLT with jQuery templates.
I am not saying that the two are the same, but that they are similar. Are there lessions that we learned with XSLT that can be applied here?
Dave, for some reason i can’t get your script to work. Do you mind to post a sample, when you have a chance?
Thank you.
Here’s the code from the post, all assembled: http://encosia.com/source/invoice-template-composite.htm.txt
Wouldn’t it be possible to simply use the same “templating” as used in a asp:repeater or asp:listview->layouttemplate!? Then we could reuse the styling in both worlds.
Simple yet obvious.
Still deserves an erection for its power.
Very clear article, Dave!
Is this solution SEO friendly, or is target is only intranet or scenario where SEO friendly is not a must.
Thanks
Definitely not SEO friendly. As far as search engines are concerned (for now, currently), content dynamically rendered on the client-side doesn’t exist.
In your example, the JSON data being rendered contains values such as price: 450.00. But, when it is rendered you show the HTML as $450.00. How/when are you applying the money formatting on the client?
I skipped that in the code to keep the example focused on composition (probably should have removed the currency formatting from the markup in the first section).
Formatting currency during templating is easy though. Since you have access to the global scope, you can use any JavaScript currency formatting snippet you want. Just add a currency formatting function to the page and then change
${price}to${yourCurrencyFormatter(price)}. The template will render the result of the formatting function in place of the entire token.Dave,
I like the idea however can you explain how its better for ASP.Net MVC rather than return a Partial View with the model passed to it from an Action that was requested via AJAX.
In your example you have to make a server side call anyway to get the data so why not return the view as well?
I think client-side templating has a couple primary advantages over returning partials (AJAH, as it’s often called).
First, returning raw data is faster on the server-side and lighter-weight over the wire. I like to explain returning pre-rendered HTML like returning 5 + 5 + 5 + 5 + 5, whereas returning data and template is like returning 5 x 5. As the quantity of items to render grows, AJAH becomes less and less efficient.
Having the template available on the client-side also gives you the ability to provide a much more interactive experience. For example, if I’ve rendered the “invoice” in this example and then want to allow the user to add more line items to it, my UI isn’t dependent on any further round-trips between the server. I can instantly render what a new line item should look like, while attempting to save it, instead of having to wait until it’s submitted and its HTML representation is returned.
It’s not perfect though, of course. If SEO or screen reader accessibility is important for particular content, that content needs to be generated on the server-side (or at least have a server-side fallback, progressively enhanced to the client-side approach for capable client).
@Jon,
Your can return a JsonResult from your view, in which case the templates are a great way to render the page content.
The JsonResult would be from the action in MVC.
I guess the question is would it be quicker to return a JsonResult from an Action and pass the data to the jQuery template or to do a AJAX request to an Action that returns the html from a partial view and on success append it to an element
Thanks that helps.
How does this compare to razor inline templates?
jQuery Templates isn’t very similar to Razor, other than their both being some form of a view engine (though, there is a partial .NET implementation of jQuery Templates that runs on the server-side now, which makes them more similar).
Dave,
What I meant was performance really? From the outside it seems very similar. You return a model and pass it to the template and then render it.
“there is a partial .NET implementation of jQuery Templates that runs on the server-side now”
Dave… can you post a link? Any experience with this?
https://github.com/awhatley/jquery-tmpl.net
I don’t have any personal experience using it.
Looks like jQuery Templates is no longer actively in development and is now deprecated.
https://github.com/jquery/jquery-tmpl
That’s right. It’s being replaced with a similar library called JsRender, which has the same syntax for simple templating, but is string-based instead of DOM-based so it’s faster and can be used in DOM-less scenarios like server-side rendering with Node.js.
You can read more about what’s going on here: http://www.borismoore.com/2011/10/jquery-templates-and-jsviews-roadmap.html
Oh yea… nice! Back to experimenting!
Great article and I plan to use the technique. In my project, I will need to load images into a repeater row column from a web service that streams the image. I would like to use AJAX to load these images, after the textual data is rendered in the repeater. Can you suggest how I might approach this?
was just about to start using templates until I ran into the bad news and deprecation news. Any recommendations now for what template library to use for this kind of thing?
BTW, great article!!! thanks for posting
If you want the spiritual successor to jQuery Templates, check out JsRender.
That said, I’m still using jQuery Templates and jTemplates in some of my older projects and haven’t found any need to migrate. So, if you prefer jQuery Templates’ syntax or DOM-centric approach more than some of the others (jQT is relatively unique in allowing arbitrary JS in templates, for example), I wouldn’t worry too much about using it anyway.
Great article, plain and simple !!!