I spent some quality time with Dave Reed’s latest revision of John Resig’s jQuery.tmpl plugin recently, migrating a small project from jTemplates. Since both the jQuery team and Microsoft team have requested feedback on jQuery.tmpl, I decided to write about my experience using it (as I am wont to do with these templating proposals).

Overall, jQuery.tmpl is a great step in the right direction. It’s small, it’s simple, and it’s fast. Overloading append() to allow the append(Template, Data) syntax is phenomenal. That approach feels more like idiomatic jQuery than anything else I’ve used, including jTemplates.

However, if this template rendering engine is going to succeed broadly, I feel there’s one important feature still missing. Additionally, there are a couple ancillary features that are present in the current proposal, but should be protected.


Composition

One area where jTemplates still comes out on top is template composition – also known as nested templates. Specifically, this refers to the ability for templates to contain references to other templates, and the ability to render that entire group as a whole.

The need for template composition may be hard to see in simple examples, but most non-trivial scenarios benefit from template composition. Dave mentioned the example of having a person template that embeds a separate template for displaying information on one or more phone entries about those person records.

That’s a good example, but take it one more step to understand where composition really shines. Consider the possibility that each of those phone records has a type (e.g. Mobile, Home, or Work) and that each type must be presented with different markup.

Template composition provides a clean solution to this problem. By creating separate templates for each type and then rendering the correct amalgamation of those templates, the template code remains simple (but is powerful).

A composition workaround in jQuery.tmpl

Currently, something resembling nested item templates are technically possible via the each keyword in jQuery.tmpl, but it’s not pretty. This example from the jQuery.tmpl demo illustrates that approach:

Even for this most simple case, the syntax is rough. Not the sort of readable simplicity that we’ve come to expect from jQuery.

More importantly, extending that to conditionally render different fragments of markup would be much more difficult.

A cleaner workaround (but it’s a trap!)

The jQuery.tmpl demo also contains this seemingly elegant alternative:

By embedding a function in the data, referencing that object key in a template returns the result of the cityJoin function. Thus, jQuery.tmpl renders the function’s result, not the function declaration’s actual text.

That technique dramatically simplifies the template itself:

While that approach does succeed in avoiding the messy template code that each requires, it tightly couples concerns which should not be.

When this is put into practical use, the data object will usually be requested from the server-side. Would my business logic or data repository tier need to inject the joining function? I don’t think I could bring myself to do that.

Further, it doesn’t really address the real-world scenarios I’ve encountered. A callback function to format data won’t feasibly scale to rendering heterogeneous chunks of markup. Effectively, it’s the same as the each solution, with the pain point shuffled around a bit.

How I think it should work

As long as there’s some way to name and render sub-templates, I don’t care how exactly it works.

I wasn’t crazy about jTemplates’ {#include} syntax at first, but it’s okay once you get used to it. Most any syntax shouldn’t be difficult to learn and acclimate to.

Since jQuery.tmpl already provides for caching the templates in jQuery.templates, all that’s really necessary is a method for rendering those named templates within other templates.

A concrete example

This example simplified a bit, but is functionally similar to client work I come across regularly. To be clear, this is something I’m currently using today, not something I’m just theorizing as a good idea.

I want to be able to take data that isn’t necessarily homogeneously structured:

And use a set of templates like this to render that data (did I get the each syntax right in #Invoice?):

Scenarios just like that one are common in my current work with jTemplates. Imagine trying to implement that with each or an embedded callback function.

Now imagine you wanted to conditionally render those same row templates as sub-items in more than one master template (e.g. maybe there’s also a credit memo template similar to the invoice, but not identical). The burden of maintaining an application like that quickly compounds without template composition.

Again, the exact syntax doesn’t matter. Any implementation that provides the functionality would be a win.

External templates

I’ve never understood the desire to cruft up a page with inline templates. Whether they’re hidden through CSS or embedded within a text/html type script element, cluttering my markup with templates feels sloppy.

jTemplates introduced me to the idea of storing templates externally, and then asynchronously loading them only as necessary (example). I adopted that approach at nearly the same time I began using jTemplates and haven’t looked back since.

My affinity for remotely template loading caused me to lobby for remote templates both in the DataView and more recently in jQuery.tmpl. However, what I hadn’t considered is that it’s already easy to load external templates with jQuery’s built in AJAX functionality. With the template loaded into a string variable, the append(TemplateString, Data) syntax connects the dots perfectly.

All of that is simply to say: Please do leave the append(TemplateString, Data) syntax intact. As long as we can provide templates via string variable, built in remote template loading isn’t necessary.

On the need for in-template logic

I’ve heard some dissention on the issue of conditional logic within templates.

Philosophically, I agree; mingling logic into your presentation/view is dangerous. It’s always a slippery slope, at best. However, the pragmatist in me ultimately cannot agree with the hard-line approach of banishing it completely.

A screenshot of conditionally rendering invoice display names depending on their invoice numberA project I’m working on is a good example. My client-side code must display a collection of invoices sourced from a legacy backend, each with an upgrade number. Upgrade 0 must be displayed as “Original Invoice”, but the rest should be displayed as “Upgrade n”.

A conditional in the template makes quick work of the problem (this is jTemplates syntax, not jQuery.tmpl):

Since it’s purely presentational logic, it belongs in the template as much as it does anywhere. Please do keep that functionality available, even if it does have potential for abuse.

In addition to the currently available conditional keywords if and else, elseif and switch would both be nice additions.

Conclusion

Overall, I’m excited about the potential of seeing jQuery.tmpl integrated into jQuery core, or even made available as an “official” plugin. As much as I like jTemplates, support and documentation for it is spotty at best.

Ultimately, we will all benefit from standardizing on an official templating solution rolled into the jQuery core, rather than each of us using our obscure favorite.

I’m curious what you think. Am I the only one using template composition? Anyone want to make a convincing case against conditional logic in templates?