Not Using jQuery JavaScript Templates? You’re Really Missing Out.

In preparation for my upcoming talk on jQuery Templates, I’ve been been deep diving into the jQuery Template plugin created by Microsoft.. Many of you are probably familiar with server-side template engines like Smarty or Cheetah but only recently have client-side template engines taken off. Considering how complex our web apps are becoming, it makes total sense.

The cool thing about templates is that it lets you easily structure your content display without all the hassle of string concatenation. For example, say I had a data set containing an ID and a name and I wanted to display the name as a hyperlink.

I could do something like this:

[code language=”js”]
var clRec = "";

for(var i=0; i<client.name.length; i++) {
clRec += "<li><a href=’clients/"+client.id[i]+"’>" + client.name[i] + "</a></li>";
}
[/code]

but to me, this seems much more readable and maintainable:

[code language=”js”]
<li><a href="clients/${id}">${name}</a></li>
[/code]

The second code snippet is a template I’ve created to render a hyperlinked name in a list and it’s very easy to do. First, include both jQuery and the jQuery Template plugin into your page:

[code language=”js”]
<script src="http://code.jquery.com/jquery.min.js" type="text/javascript"></script>
<script src="jquery.tmpl.js" type="text/javascript"></script>
[/code]

Next, define the data that you’d like to see rendered. This could be data derived from an XHR call or something you’ve predefined, like this:

[code language=”js”]
var clientData = [
{ name: "Rey Bango", id: 1 },
{ name: "Mark Goldberg", id: 2 },
{ name: "Jen Statford", id: 3 }
];
[/code]

Now, define your template:

[code language=”js”]
<script id="clientTemplate" type="text/html">
<li><a href="clients/${id}">${name}</a></li>
</script>
[/code]

Yep, the “script” tags are necessary and used because they allow your template to be embedded within the body of the page. Notice that we’ve defined the placeholders as ${id} & ${name}, the same names used in the identifiers in our data. The “${}” tells the template parser that the field needs to be replaced with the expected value.

Then call the jQuery Template plugin to render the data using your template:

[code language=”js”]
$("#clientTemplate").tmpl(clientData).appendTo( "ul" );
[/code]

The plugin’s .tmpl() method accepts the data we’ve defined and handles the parsing of the template we’ve selected. Then we use jQuery’s .appendTo() method to append the results to an unordered list tag. This gives me the following results:

That’s it! Told you it was simple. :)

I’ll go into more advanced details during my presentation but this should give you something to start with in the meantime. Here’s the full source for you to use:

[code language=”html”]
<!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", id: 1 },
{ name: "Mark Goldberg", id: 2 },
{ name: "Jen Statford", id: 3 }
];

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

});
</script>

<script id="clientTemplate" type="text/html">
<li><a href="clients/${id}">${name}</a></li>
</script>

</head>

<body>

<ul></ul>

</body>
</html>
[/code]

Rey Bango

76 Comments

    • hehe. Very cool. After many years of being a Ray Camden fanboi, it’s now being turned around. :D

      Of course Ray. I put that code up for anyone to use. Go for it. :)

    • How does that compare to other templating options like Distal code.google.com/p/distal or Mustache mustache.github.com , please do a writeup.

      • Not really sure since I’ve not used those other libs. As for a writeup, I don’t expect to have time to do one so your best bet is to take what I’ve done and compare all three.

  1. I certainly love templates… oh, so many hand-crafted document fragments! Buuut… how the heck did John Resig’s beautiful 20-odd line micro-templating code turn into THAT?!

    • I haven’t used John’s but note that John is actively providing feedback to the MS team on that plugin and that feedback has been incorporated into the plugin.

      • The original templating code was here: http://ejohn.org/blog/javascript-micro-templating/ – someone had put out a fix a “single quote” issue… can’t find it right now. Looks like it’s done a bloat-morph into something huge now – obviously it must contain some better features, but if all you want is to do the templating examples you’ve done in the code above, then the tiny (jQuery-free) solution might be better!

  2. The owner of this project on GitHub is “nje (.NET jQuery Extensions)”. Is there anything .NET-specific here? This looks like it can be used anywhere.

    • Nothing .NET specific at all. That’s just the name the Microsoft team chose for their account. They’re working with the jQuery team on these plugins as well and are following the jQuery Project’s contribution guidelines.

    • Yep. That was a very cool use of it. Note that you may want to update the code to use the new .tmpl() method since .render() has been deprecated.

      • Rey is there an official web site for the plugin besides the github repository? It’s hard to keep up with a plugin via each commit.

        Would really like a point release of the plugin that explains what’s changed.

        I did not know they changed render -> tmpl nor would I unless you said something.

        • Github is the only place at the moment. I spoke with the team and they’ll be updating the API docs soon.

  3. Awesome work Rey. Is it possible to put the “text/html” script block in an external file?

      • You should be able to add the template block at anytime in the life cycle of your page. However before you use this or the micro-templating engine it must exist to actually work. It would be no different than any other DOM element on the page. The text/html thing is a trick to keep the browsers from evaluating the block as a js block.

    • Brian Wilpon,
      It is not possible. This is a huge, and overlooked, problem with most templating solutions. At some point, you don’t want all your templates to be sent inline, just like you don’t want scripts inline.

        • Actually it is possible…

          document.write() is your friend, put the whole template including the script tags in there. Not a very nice solution but it works ;)

    • If the external file is on the same domain, you can just build a small script that search all script[type=’text/html’] and pull them in with an AJAX request.

  4. The templates are great…but I do see the potential for misuse that I’d like to chime in on. In general, I would say that jquery javascript templates should really only be used for the display of dynamic, non-SEO relevant data, since search engines do not parse javascript.

    I see the temptation, especially in DNN, to rely on client side templating for more than just this type of dynamic data display. For instance, you would not want to use javascript templating on something like Forum posts, or comments on a blog (such as this)…since that is unique and relevant content that has great SEO value.

    Just my 2 cents worth. :)

    • Depending on your use case, you can also use the data that is already present on your page and feed that in to the template engine. Allowing you to provide a richer experience for those who have JavaScript enable for example ;)

    • Google now parses javascript on a simple level, and they’re working to broaden their abilities. It’s a recent thing …

    • Great point, I have been contemplating what is the best architecture when it comes to AJAX and SEO needs. behind the firewall, it does not matter so much, but for a public site that needs good positioning you need to make sure the important info is on the page without any AJAX needed to load it IMO.

  5. you should really attribute the plugin to john resig. he wrote the original. ‘nje’ just added a bunch of extra code to it. seems redundant to me, unless you can provide a demo of those features, and not just the core feature already provided by resig’s code.

    • Not sure why I would. This is an independent plugin and while some code is based off of John’s work, it’s gone off on its own and added a number of features. In fact, John & I are working with the Microsoft team to improve this specific plugin and is being considered for official plugin status.

      As far as showing you a demo of the extra features, you should check out the plugin to see what’s available. Sounds like you haven’t really done that and there’s no sense in waiting for me. :)

      • Wrong. It was created by John Resig, and forked by Boris (who works at Microsoft). He may have made major contributions, but saying the plugin was “created by Microsoft” is nonsense.

        • Hi Brandon. You’re pretty snarky, especially for someone who wasn’t there when it was being built. On the other hand, I was actually there because I was a member of the jQuery Project team and an employee of Microsoft when it was in development. In fact, John, Boris & I had plenty of chats about this new version of the templating engine.

          jQuery tmpl and John’s Micro Templating experiment are incredibly different in both code bases and functionality. It’s quite possible that Boris may have looked at John’s original code but what John & Boris built are vastly different. Just look at John’s code and Boris’ code.

          Further, John mentioned the fact that we had originally considered using his Micro Templating engine but the new Microsoft version was much more robust. via Ajaxian:

          “John told me his original Micro-Templating library was considered at one point, but the new templating is more refined.”

          So yes, the jQuery templating plugin was created by Microsoft and leveraged a lot of the in-house knowledge that MS had in their own JS-based templating functionality.You’re grossly underestimating the work that went into this and the amount of MS in-house knowledge that was leveraged. And if you look at JSRender, the better version of jQuery tmpl, the differences are even more obvious.

          Lastly, please tone done the snarkiness and try a more friendly approach. It goes a lot farther with me.

          • You say “It’s quite possible that Boris may have *looked* at John’s original code” but Boris clearly states that he forked John’s code. If you were there you should know this.

            The question of how different they are is a red herring. The point is that it did not originate at or with Microsoft the way you claim. No matter how much Boris (or other Microsoft employees) changed it, it did not originate inside Microsoft. Boris is quite up-front about this, so why can’t you be? I’m in no way putting down his contributions, as I’m sure they are very considerable. But no matter how sizable his contributions were, your claim is false. Someone already pointed this out to you and you dismissed them. Now you say I’m snarky for pointing it out more bluntly.

          • So it sounds like we’re arguing semantics.

            I’m saying the Microsoft created the plugin, as in “built it”. I clarified in a subsequent reply to you that it was a fork of John’s original code but the end result is vastly different and it’s a totally different plugin. All you have to do is look at the code. If you’ve done that, you’ll see it. That to me constitutes a whole new creation and one that was built by Boris (and Microsoft). He had input from the jQuery team as to how to create the API to better fit within the jQuery style.

            What I’m reading from you is that your point of contention is that the idea didn’t originate from MS. Is that correct?

            And yes, you were being snarky. Certainly happy to have a conversation but completely uninterested in your bluntness.

        • And just to be clear, the original was a fork, just as Boris mentioned before but the end result is very far from what John’s original code was, especially in JSRender.

  6. I started putting this script to use and thought about a very nice addition. Wouldn’t it be nice if the data object that was passed through was added to the template’s parent element’s data cache? Accessible via $.data.

    Also, is the current build able to treat some data as HTML? So line1<br/>line2, will show as:

    line1
    line2

    rather than ‘line1<br/>line2’.

    Excellent work :)

  7. @John Strickler
    There’s a context that is accessible that contains everything you have access to within the template. You can retrieve a context from any element inside the instance of the template: $(selector).tmpl().data.

    For writing content you want to allow html in,
    {{html foo}}

  8. Thanks for the various comments above.

    To give a bit of context, this is a fork of John’s prototype, which we have been using to explore some scenarios. It is currently pretty much in flux, so we haven’t been drawing attention to it up to now, or providing API documentation. But quite a few of the recent changes are actually a result of input from John, following his review of where we were at a couple of weeks ago.

    As to the set of features, nothing is decided yet – we are aiming at splitting it into a set of more important features (currently jquery.tmpl.js) and some additional features in a separate plugin (jquery.tmplplus.js). But which parts go in which is under discussion with John, and things could move in either direction.

    There is quite a lot that was not at all in John’s original prototype, including composition through the {{tmpl}} tag (partials), being able to get to the template context (which provides access to the data item, the HTML nodes, the parent context – for nested templates, etc.), improved support for passing parameters to tags in markup, and so on. Take a look at the sample demos, including the movies demo, to get a sense of some of the features that are currently in there.

    On the documentation, we will add a Wiki to the github repo very soon, and also try to add more demos as we move along…

    Absolutely agree about being able to use external/remote templates, and that is on the roadmap, though some workarounds are already available.

    • Just wanted to point out that John’s original prototype doesn’t actually require any changes in order to enable features like partials (nested templates) or counting iterators. I was able to plug those features in through John’s tmplcmd interface.

      The tmplcmd’s themselves are discreet one or two line decorators that aren’t tightly coupled with the core tmpl engine. I prefer that approach, since it keeps specific use cases out of the general templating engine.

      When I looked at the Microsoft approach, there were a number of added dependencies that just wouldn’t be useful 80% of the time. The additional API for event-binding, prerendering and postrendering seemed overly complex too, especially in a world with jQuery delegate().

  9. I don’t get. What’s the whole purpose of loading javascript libraries and rendering data into a template with javascript. What is wrong with the normal way of outputting data in Coldfusion, PHP, etc? It is just a template after all. If you need to do some manipulation afterwords without making a server call then use javascript, but for templating???? Help me understand.

    • It reduces traffic because the template is cached in the js-file. If you use PHP, CF, etc templates, you have to transfer the template every time you use it.

  10. Pingback: DotNetShoutout
  11. One thing that seems like a potential deal-breaker for some, unless I’m missing something, is the incompatibility with server-side expression language or templating syntax used by Java’s EL within JSP files and Grails’ GSP files. Does anyone know if there is the option of defining a different wrapper then the default ${} provided with this templating engine?

    It would obviously only cause issues with JS contained within a server-side parsed file, but that could definitely cause enough disincentive.

  12. Like the template in a template feature, nice one! Using it as template in a template in a template :D

  13. @JGarrido
    For the case where you are using a server-side expression language which uses the ${foo} expression, you can just use the longer form, client-side: {{= foo}}.

    Client-side, ${foo} is just a shorthand for {{= foo}}, so the two forms are completely equivalent…

    • Ah great to know, that would certainly resolve it. Maybe I’ll take a look at it after all, thanks for the tip.

  14. I’ve never seen raw HTML inside a script tag. Frankly this bit of code scares the shit out of me.

    A script tag with a mime-type of ‘text/html’. Oh the horror! Is this a HTML5 thing. Does HTML5 allow this super-hacky way of writing code?

  15. Hey Ray,

    I thought I’d plug my own little templating engine here as my benchmarks were quoted by Harry above.

    You guys might want to have a look at http://aefxx.com/jqote-plugins/jqote2. The first version was originally based on Resig’s brilliant code snippet that has/had some shortcommings (mainly parsing and caching), though.

    jQote2 then was rewritten from scratch, faster, more stable and now offers (almost) everything you’d ever want from a client-side templating solution:

    – Template precompilation to JavaScript lambdas (i.e. functions)
    – Caching mechansim to ease the compilation perfomance hit
    – Convenience methods to append/prepend and substitute template outcome within a container
    – Custom jQuery events that feature live/delegate binding
    – Exception handling that aids in debugging errorneous template code

    Give it a try. You won’t regret it.
    Nice day,
    aefxx

    • Hehe no worries. I’m glad you came over. Having different options is great. I even mentioned jQote in my presentation on Monday on jQuery Templating.

  16. I’m confused with this specific example. If you have to enter the data, why not just enter it in the UL and cut down on the amount of code in the page? Granted, this example is small, but why assign data to a variable and then enter that actual data for the variable in the html?

    The point should be able to be given an xml file or a comma-delimited text file, or excel or whatever that has scads of information that one would want to utilize in the given format. Then, a small generic script is written to say “go to the file and grab column A and assign it the variable “name” then, put that value in the page here..”

    A template seems to just be a different approach to a plug-in just like an ipod cast is just a mp3

    • @lenny: Yes of course grabbing remote data would be the most likely use case. I’m providing a variable containing data so readers can work with it. If you look at the demo code I recently uploaded from my presentation you can see it uses an XHR call to return JSON data and render it in a template.

  17. Hi,

    This library is great but unfortunately seems not work with jQuery 1.3.2, I get an error (“pntNode is null” in processItemKey function). Is it necessary to move to jQuery 1.4 or do you have a workaround or advices please ? thans a lot.

  18. Hey Rey,

    I have a question:

    Is there a way to relate the original data used to render the template with the rendered elements?

    Suppose I have my data array that I use to render the template. Once it’s rendered, I update some of the generated markup, how can I update the original data array used to render?

    I’m creating a layout builder, which has internal elements that can be updated with a form that popups when you click each element. My plan is to store the data array into a database, that’s why I need to update it.

    Is this something doable? Is there another way to approach this problem?

    Thanks a bunch!

  19. This is definitely great tech, but almost a year after this post the Templates are still beta – “This plugin is currently in beta form and may change significantly before version 1.0 is released.”

    Many project require a 1.0 version – are you seeing reasonable progress towards a 1.0 release? Thanks.

    • Hi Steve,

      The effort is now part of the jQuery UI project which is looking at how to integrate it into the project’s architecture: Roadmap

      I would say to check out JsRender which is being curated by the original developer of jq-tmpl and is an optimized version of it as well as JsViews which incorporates data linking into the templates.

      • Hi Rey – the Roadmap link definitely helps me in determining how/when to use templating & what to keep an eye on moving forward. Thanks for your help!

  20. Also worth checking out is json2html (www.json2html.com), a plug-in for jQuery, that uses JSON templates that do not require compiling.

  21. How easy is it to alternate styles, for example between the list items? Because if using a straight JavaScript loop, this would be trivial, ugly, but trivial. If using templates, I’m a bit dependant on the options available, not to mentions that I need to learn yet another skill. Can you please give the alternating styles as an example for how easy it is.

    With kind regards,
    Oren

    • Not really sure how easy it is but it could be a simple matter of using CSS psuedo classes to search for alternating rows and apply styles.

  22. Thanks Rey for this post. I’m obviously getting to this a little late, but I think still relevant to what I’m wanting to accomplish in terms of an artist site I’m wanting to create. I found this post through your series of Nettuts articles regarding Ember.js. Thanks for both!

Comments are closed.