jQuery API

jQuery Plugin

jQuery.tmpl()

jQuery.tmpl( template [, data] [, options] ) Returns: jQuery

Description: Render the specified HTML content as a template, using the specified data.

  • version added: 1.4.3jQuery.tmpl( template [, data] [, options] )

    templateThe HTML markup or text to use as a template.

    dataThe data to render. This can be any JavaScript type, including Array or Object.

    optionsAn optional map of user-defined key-value pairs. Extends the tmplItem data structure, available to the template during rendering.

This documentation topic concerns the jQuery Templates plugin (jquery-tmpl), which can be downloaded from: http://github.com/jquery/jquery-tmpl.

The jQuery.tmpl() method is designed for chaining with .appendTo, .prependTo, .insertAfter or .insertBefore as in the following example.

Example:

$.tmpl( "<li>${Name}</li>", { "Name" : "John Doe" }).appendTo( "#target" );

The template parameter can be any of the following:

  • A string containing markup.
  • An HTML element (or jQuery object that wraps an element) whose content is to be used as the template.
  • A string corresponding to the name of a named template (see jQuery.template() and .template()).
  • A compiled-template function (see jQuery.template() and .template()).

If data is an array, the template is rendered once for each data item in the array. If data is an object, or if the data parameter is missing or null, a single template item is rendered.

The return value is a jQuery collection of elements made up of the rendered template items (one for each data item in the array). If the template contains only one top-level element, then there will be one element for each data item in the array.

To insert the rendered template items into the HTML DOM, the returned jQuery collection should not be inserted directly into the DOM, but should be chained with .appendTo, .prependTo, .insertAfter or .insertBefore, as in following example:

$.tmpl( myTemplate, myData ).appendTo( "#target" );

See also .tmpl().

Example

The following example shows how to use jQuery.tmpl() to render local data, using a template provided as a string:

<ul id="movieList"></ul>

<script type="text/javascript">
  var movies = [
      { Name: "The Red Violin", ReleaseYear: "1998" },
      { Name: "Eyes Wide Shut", ReleaseYear: "1999" },
      { Name: "The Inheritance", ReleaseYear: "1976" }
  ];

  var markup = "<li><b>${Name}</b> (${ReleaseYear})</li>";

  // Compile the markup as a named template
  $.template( "movieTemplate", markup );

  // Render the template with the movies data and insert
  // the rendered HTML under the "movieList" element
  $.tmpl( "movieTemplate", movies )
      .appendTo( "#movieList" );
</script>

Using Remote Data

Typically the data is not local and is instead obtained using an Ajax request to a remote service or page, as in the following example:

var markup = "<li><b>${Name}</b> (${ReleaseYear})</li>";

// Compile the markup as a named template
$.template( "movieTemplate", markup );

$.ajax({
  dataType: "jsonp",
  url: moviesServiceUrl,
  jsonp: "$callback",
  success: showMovies
});

// Within the callback, use .tmpl() to render the data.
function showMovies( data ) {
  // Render the template with the "movies" data and insert
  // the rendered HTML under the 'movieList' element
  $.tmpl( "movieTemplate", data )
    .appendTo( "#movieList" );
}

The Markup for the Template

You can get the markup for the template from inline markup in the page, or from a string (possibly computed, or obtained remotely). For an example of how to use inline markup, see .tmpl().

Caching the Template

When a template is rendered, the markup is first converted into a compiled-template function. Every time $.tmpl( markup , myData ).appendTo( "#target" ) is called, the template is recompiled. If the same template is to be used more than once for rendering data, you should ensure that the compiled template is cached. To cache the template when using markup that is obtained from a string (rather than from inline markup in the page), use $.template( name, markup ) to create a named template for reuse. See jQuery.template().

Template Tags, Expressions, and Template Variables

Template tags such as the ${} tag can used within jQuery templates in addition to text and HTML markup to enable a number of scenarios such as composition of templates, iteration over hierarchical data, parameterization of template rendering, etc. Template tags can render content based on the values of data item fields or template variables such as $item (corresponding to the template item), as well as expressions and function calls. See the documentation topics for each template tag: ${}, {{each}}, {{if}}, {{else}}, {{html}}, {{tmpl}} and {{wrap}}.

The options Parameter, and Template Items

Each template item (the result of rendering a data item with the template) is associated with a tmplItem data structure, which can be accessed using jQuery.tmplItem() and .tmplItem(), or the $item template variable. Any fields or anonomyous methods passed in with the options parameter of jQuery.tmpl() will extend the tmplItem data structure, and so be available to the template as in the following example:

var markup = "<li>Some content: ${$item.myMethod()}.<br/>" 
           + " More content: ${$item.myValue}.</li>";

// Compile the markup as a named template
$.template( "movieTemplate", markup );

// Render the template with the movies data
$.tmpl( "movieTemplate", movies,
  { 
      myValue: "somevalue", 
      myMethod: function() { 
          return "something";
      } 
  } 
).appendTo( "#movieList" );

Additional Notes:

  • Netflix recently changed the API that we use in the remote service example below. We are aware that this change breaks the demo and will work on an update as soon as we can.

Examples:

Example: Render local data using jQuery.tmpl().

<!DOCTYPE html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
  <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
</head>
<body>
  
<ul id="movieList"></ul>

<script>
  var movies = [
  { Name: "The Red Violin", ReleaseYear: "1998" },
  { Name: "Eyes Wide Shut", ReleaseYear: "1999" },
  { Name: "The Inheritance", ReleaseYear: "1976" }
  ];

var markup = "<li><b>${Name}</b> (${ReleaseYear})</li>";

/* Compile the markup as a named template */
$.template( "movieTemplate", markup );

/* Render the template with the movies data and insert
   the rendered HTML under the "movieList" element */
$.tmpl( "movieTemplate", movies )
  .appendTo( "#movieList" );
</script>

</body>
</html>

Demo:

Example: Render data from a remote service, using jQuery.tmpl().

<!DOCTYPE html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
  <script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
</head>
<body>
  
<button id="cartoonsBtn">Cartoons</button>
<button id="dramaBtn">Drama</button>

<ul id="movieList"></ul>

<script>
var markup = "<li><b>${Name}</b> (${ReleaseYear})</li>";

/* Compile the markup as a named template */
$.template( "movieTemplate", markup );

function getMovies( genre, skip, top ) {
  $.ajax({
    dataType: "jsonp",
    url: "http://odata.netflix.com/Catalog/Genres('" + genre
    + "')/Titles?$format=json&$skip="
    + skip + "&$top=" + top,
    jsonp: "$callback",
    success: function( data ) {
      /* Get the movies array from the data */
      var movies = data.d;

      /* Remove current set of movie template items */
      $( "#movieList" ).empty();

      /* Render the template items for each movie
      and insert the template items into the "movieList" */
      $.tmpl( "movieTemplate", movies )
      .appendTo( "#movieList" );
    }
  });
}

$( "#cartoonsBtn" ).click( function() {
  getMovies( "Cartoons", 0, 6 );
});

$( "#dramaBtn" ).click( function() {
  getMovies( "Drama", 0, 6 );
});

</script>

</body>
</html>

Demo:

Support and Contributions

Need help with or have a question about it? Visit the jQuery Forum or the #jquery channel on irc.freenode.net.

Think you've discovered a jQuery bug related to ? Report it to the jQuery core team.

Found a problem with this documentation? Report it on the GitHub issue tracker

  • Trey

    The example in the section entitled “The options Parameter” is not valid javascript. Unless my brain isn't working properly setting a function in an object still requires the colon syntax.

  • http://developerspage.wordpress.com Ankit Bhatia

    The data in above examples is in array format. Is it possible to use XML or JSON instead?

    • http://borismoore.com BorisMoore

      The data can be any JavaScript type – in particular objects or arrays. (JavaScript object graph, if you will.) JSON can be the format over the wire of course and it will eval to an object graph. For XML, no, not yet…

    • http://www.borismoore.com Boris Moore

      The data can be any JavaScript type – in particular objects or arrays. (JavaScript object graph, if you will.) JSON can be the format over the wire of course and it will eval to an object graph. For XML, no, not yet… You would need to convert it to JSON, or equivalently, to nested objects and arrays.

  • Dom Ioanna

    Would it be possible to run this with an XML dataset?

    • http://borismoore.com Boris Moore

      No, you would need to convert your XML Document to a JavaScript 'object graph' of some kind – nested objects and arrays. Maybe in a future version. But currently the template tags undestand JavaScript expressions, not the XML Document API.

  • http://twitter.com/richard_lopes richard_lopes

    Instead of creating again a double-bracket template engine, why not using the less invasive approach from Pure ? I am using their solution and it just feel more natural than anything else. Relying on HTML instead of reinventing the wheel. Faster learning curve. Curious people can google Pure from Beebole.

  • Tyler

    For the template, can the JavaScript objects properties have spaces in them? Such as:
    var movies = { “Movie Title” : “Batman” };
    And then be used in a template like:
    <li>${Movie Title}</li>
    When I do this I get nothing rendered from the template. Is this supported currently?

    • http://borismoore.com Borismoore

      You can do: ${$data["Movie Title"]}

      Or you can do ${getName()} and define a function called getName in which you return
      this.data["Movie Title"]

    • http://borismoore.com Boris Moore

      You can do: ${$data["Movie Title"]}
      Or you can do ${getName()}
      and define a function called getName() in which you return
      this.data["Movie Title"]

      • Tyler

        Awesome! I was worried that might have been overlooked, but glad it wasn't. When I get a chance I will work on converting over our custom template implementation we made to use the JQuery implementation instead…keep up the great work!

      • zac

        ..btw I found that I needed to do the same with javascript reserved words, so:

        {{= item['class'] }}

        NB. {{= item.class }} works fine in all browsers , FF, Chrome, Safari, Opera, but fails in IE. e.g. IE8 error:

        Message: Expected identifier
        Line: 314
        Char: 3
        Code: 0
        URI: http://localhost:8080/js/plugins/jquery.tmpl.js

        • http://www.borismoore.com Boris Moore

          If you have ${foo} or {{= foo}}, then foo is evaluated as a JavaScript expression. Evaluation is in the context of with($data) (JavaScript with statement). So everything follows from that. In JavaScript if you have an object dataItem with keys “class” or “a-b” or “a b”, then dataItem.class will not work in IE, and dataItem.a-b or dataItem.a b will not correspond to what you want. For those keys you have to do dataItem['key']. This is JavaScript behavior, and is not specific to the templates. (Given we opted for a design which supports JavaScript expressions). Make sense?

          • zac

            naturally! ace thanks. this plugin is so nicely written – beautiful sys. really enjoying working with it !

      • ameya kogje

        Hi, I was directed here from github (http://github.com/jquery/jquery-tmpl/issues/closed#issue/3). The IE8 issue described there is about white space in the value of attribute and not the key.
        Object:
        var company = { companyName: 'ABC ASDF' };
        Template:
        <input id=”companyName” name=”companyName” type=”text” value=”${companyName}”>
        Output:
        <input asdf=”" id=”companyName” name=”companyName” value=”ABC”>
        Here, using ${$data['companyName']} instead of ${companyName} solved the issue.
        New Output:
        <input id=”companyPhone” name=”companyPhone” value=”a b c”>
        Does that mean I must not use ${companyName} format at all (for any attribute whose value can have white spaces)?

        • http://www.borismoore.com Boris Moore

          You are right, the issue was about spaces in the value. No, you should not have to use $data['companyName']. ${companyName} should work fine. (Following up also by email with ameya).

          • http://www.borismoore.com Boris Moore

            Turns out this is because Ameya had a template in a div, not a script tag.

            In IE, the innerHTML of the div has attribute quotes removed when there is white space in the value, etc. So if you have `value=”${companyName}”` as an attribute value, and the value of companyName has white space in it, this breaks.

            Workaround:
            replace value=”${companyName}” by value=”${ companyName }”,
            or better, wrap the template in a script tag, not a div.

  • http://aery.posterous.com Hairiemx

    Currently I use the technique from john resig micro template. I prefer the template to be cached by function. For example, use $.tmpl(“template code”) to convert the template into a function that can be reused many times. I

    • http://borismoore.com Boris Moore

      That's still available in the jQuery Templates plugin. The return value of $.template, or .template is the compiled-template function.

      You can do:

      var cachedTemplate = $(“#mytemplate”).template();

      or

      var cachedTemplate = $.template(mytemplateMarkupString);

      And you can use it as in $.tmpl( cachedTemplate, data ).appendTo(…);

      You can also call it as a function, but you have to pass the jQuery object as first parameter, and then the equivalent of the template item as the second. See this as an interesting use scenario. http://github.com/nje/jquery-tmpl/issues#issue/16.

      I hope we will make this scenario of using a template to render out data as a string more discoverable and more 'friendly' as an API in an upcoming version.

  • Saetia

    Anyone else noticing how slow this is compared to a simple while loop and .join?

  • Allstealth

    What about passing one of the data properties as an html? var foo ={ picture: '<img src''=”">' }

    • http://www.borismoore.com Boris Moore

      Yes, you can do that. If you want the markup to get rendered into the DOM, use {{html picture}} rather than ${picture}. Take a look at the documentation for the {{html}} template tag for details.

      • Allstealth

        worked like a charm, thanks!

  • Santhosh Kumar

    I need to know the list of variables defined in a template. Is there any way to get that ?

    • http://www.borismoore.com Boris Moore

      Not sure what you mean by variables defined in a template. The tags generally deal with JavaScript expressions, so ${foo} will expect foo to be defined as a JavaScript variable. The template evaluation is in the context of a with($data) statement, where $data is the current data item, so foo could be a global varialble or could be a field on the $data object. You can also use $item for the current template items. Or some more complex JavaScript expression such as ${someObject.someMethod(a,b)} etc. More details are in the different doc topics…

  • http://twitter.com/bczengel Brian Zengel

    I'm having a problem with this plugin being compatible with the TinyMCE WYSIWYG editor. Any time an instance of tinymce is loaded first the template plugin will only render the first object in the template in the first iteration of the template. In other words if you are rendering a template with multiple un-nested divs using multiple data points. Only the first div of the template with the first data point will be rendered. I am using the most current stable version of the template plugin and tinymce and version 1.3.2 of jQuery.

    • http://twitter.com/bczengel Brian Zengel

      Switching from “$('#tmplTemplate).tmpl(mydata).appendTo('#divContainer');” to “$('#divContainer').append($('#tmplTemplate).tmpl(mydata));” fixed the problem. Clearly nothing to do with the template plugin and entirely to do with TinyMCE. Sorry about that.

  • http://twitter.com/davetayls David Taylor

    Hi, I have been loving using this plugin ever since the first versions were out, thanks for all the hard work!

    I have one query, is there a way of accessing the current item's index eg ${$item.index} or $i?

    Thanks

    • Public

      bump on David Taylor's question… maybe we're both missing something obvious, but I'm having a hell of a time figuring that out.

    • http://www.borismoore.com Boris Moore

      The tmplItem doesn't include a index property, by design, because if we had provided that, then we would have had to provide a way of ensuring that if you you delete or insert an item in the array, all indexes remain valid (for the items subsequent to the deleted or inserted one).

      We want to allow you to remove/insert rendered template instances from the DOM when an item is deleted/inserted from the array, without forcing you to re-render all of the items.

      So the recommended approach is to use $.inArray to determine the index in your own code.

      See examples which do just that, such as : https://github.com/jquery/jquery-tmpl/blob/master/demos/samplesCore/parameters.html

      • http://hypergraphs.de/ Axel Rauschmayer

        This problem mostly went away with the the new {{each}} and $index, right? $.inArray strikes me as unsafe in some cases, as it would not work with, say, duplicate strings in an array.

        What remains is that it is hard to detect the last element. This is needed for inserting separators. You can prefix the separator before each element and only show it if $index > 0, but that is less elegant. It would be nice to have an additional $isLast as a parameter or (similar to Array.forEach() is ECMAScript 5) the complete array.

        I have found a clean work-around for this problem: http://www.2ality.com/2011/01/

  • http://twitter.com/siravington Steven Moseley

    One of the properties I am returning back in the array is called LongDescription and it contains actual HTML. Is there a way to encode that so the HTMLis rendered on the page instead of rendering the HTML as text?

    For example, instead of rendering the image it is rendering the actual tag <img src=”…”/”>.

    • Rich

      I have the same issue, looking for an answer.

      • http://www.borismoore.com Boris Moore

        Use the {{html}} template tag. It is similar to the ${} tag, but does not HTML encode.

    • http://www.borismoore.com Boris Moore

      Use the {{html}} template tag. It is similar to the ${} tag, but does not HTML encode.

  • Vinnie Rossi

    I feel like the current data item should contain an “index” property so that you don't have to look the item up in the array to figure out whether your position is even or odd to show an alternating class.

    return ($.inArray( item, array ) % 2) ? “personAlt” : “person”;

    Instead this would just be..

    return (item.index % 2) ? “personAlt” : “person”;

    • http://www.borismoore.com Boris Moore

      See my answer to David Taylor below. That said, we will consider the trade-offs on this between the different scenarios. For the moment, we are staying with minimal implementation and covering all scenarios. (See details in my reply below).

  • Who Mobile

    Just few thought after use it with lots of learning as beginner.
    1) it works well and very clean.
    2) some part it depends on browser ( {{if abc}} in FF/IE and Chrome is different. In chrome, if abc is not exist, it use $data itself. In FF/IE, if abc is not exist, it is false. I would recommend to use {{if checkcond()}} and check this.data inside checkcond. it is much cleaner.
    3) if you have to use recursive/nested template, make cleaner conditions of recursive condition. (browser might through stack overflow exception), I recommend start with template1 -> template2->template3 before going with template1->template1… model.

    4) we need little bit more guide on how to enable debug log or how to handle exceptions. ( following basic try/catch may helpful when debugging )
    //try {
    $(“#steps”).tmpl(data).appendTo( “#status” );
    //} catch (e) {
    // console.dir(e);
    //}

    • http://www.borismoore.com Boris Moore

      Looks like the issues here are because of using the same name for a data field data.abc, and the id of an element id=”abc”. Setting an id creates a global variable, at least for most browsers. {{if abc}} will then return true even if there is no $data.abc field for the current item.

  • Solai It

    Hi,

    Inside the template i am having one table, there are five “td” elements but only 3 “td” elements only filled using database object. But i want the handler before and after rendering of all the five “td” elements. What can i do? How do i get any idea??

    Previously i used MicrosoftAjaxtemplates in that i used like following

    I just called “before” function before rendering the td element and called “after” function. Like this I need. Any idea??

    Thanks in advance.

  • Solai It

    Hi,

    Inside the template i am having one table, there are five “td” elements but only 3 “td” elements only filled using database object. But i want the handler before and after rendering of all the five “td” elements. What can i do? How do i get any idea??

    Previously i used MicrosoftAjaxtemplates in that i used like following

    <td sys:codebefore=”before()” sys:codeafter=”after()>

    </td>

    <td sys:codebefore=”before()” sys:codeafter=”after()>{{Name}}

    </td>

    I just called “before” function before rendering the td element and called “after” function. Like this I need. Any idea??

    Thanks in advance.

    • http://www.borismoore.com Boris Moore

      You can use

      {{html before}}
      <td>${foo}</td>
      {{html after}}

      Where before and after return HTML strings, such as:
      function before() { return “<td>before</td>”; }

  • Ivo

    Hi Boris,
    Thanks for that useful plug-in

    But I'm having problem with invoking global object method from the template:

    This works:

    ${MyGlobalFunc(myParam)}

    This does not work, using Firebug, I can see that error:

    ${MyGlobalObject.MyMethod(myParam)}

    illegal character
    http://nje.github.com/jquery-t
    Line 361

    I don't want to wrap object method with global function. What to do?

    Ivo

    • http://www.borismoore.com Boris Moore

      You are using nje.github. (That's the wrong repository). If you use the latest build from http://github.com/jquery/jquery-tmpl the second example should work. There was a bug on encoding of parameters which has now been fixed.

  • http://www.borismoore.com Boris Moore

    See my answer to David Taylor below. That said, we will consider the trade-offs on this between the different scenarios. For the moment, we are staying with minimal implementation and covering all scenarios. (See details in my reply below).

  • http://www.borismoore.com Boris Moore

    Looks like the issues here are because of using the same name for a data field data.abc, and the id of an element id=”abc”. Setting an id creates a global variable, at least for most browsers. {{if abc}} will then return true even if there is no $data.abc field for the current item.

  • http://www.borismoore.com Boris Moore

    You can use

    {{html before}}
    <td>${foo}</td>
    {{html after}}

    Where before and after return HTML strings, such as:
    function before() { return “<td>before</td>”; }

  • http://www.borismoore.com Boris Moore

    You are using nje.github. (That's the wrong repository). If you use the latest build from http://github.com/jquery/jquery-tmpl the second example should work. There was a bug on encoding of parameters which has now been fixed.

  • Hemant Cse31

    Thanks for super duper plugin, In my case sms section was repeated now it's solved thanks
    maza aa gaya

  • Gediminas

    Moore, it would be beneficial if .appendTo could accept jQuery object – not only selector :)

  • GazzaH

    Would it be possible to add an .html option to the existing
    .appendTo, .prependTo, .insertAfter or .insertBefore.
    I need to swap out the entire contents of a DOm element with the rendered template.

    • http://www.borismoore.com Boris Moore

      You can use appendTo, for example, but call empty() first. For example:

      $( “#container” ).empty();
      $( “#myTemplate” ).tmpl( data ).appendTo( “#container” );

      You can also do

      $( “#myTemplate” ).tmpl( data ).appendTo( $( “#container”).empty() );

  • http://twitter.com/danwellman Dan Wellman

    Here's a tip, don't use the word 'class' as a property name or it will throw 'Parser errors' in Safari and IE

    • http://www.borismoore.com Boris Moore

      You should not use any javascript reserved word for the field name of an object. If you need to do so, you can work around this by doing, for example:
      ${$data["class"]}

      ${class} will not work, for reserved words…