Categories

{{tmpl}} Template Tag

Categories: Template Tags

{{tmpl( [data], [options] ) template}}

Plugin: jQuery.tmpl

Description: Used for composition of templates. Renders one or more nested template items within the rendered output of the parent template.

  • {{tmpl( [data], [options] ) template}}

    version added: 1.0

    template   The HTML markup or text to use as a template.

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

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

Note: For information about how to render templates, see .tmpl() and jQuery.tmpl().

Template Tags

Template tags such as the {{tmpl}} tag can be used within jQuery templates in addition to text and HTML markup, in order to enable a number of scenarios such as composition of templates, iteration over hierarchical data, parameterization of template rendering, etc.

Other available tags include: ${}, {{each}}, {{if}}, {{else}}, {{html}} and {{wrap}}. User-defined template tags can also be specified, by extending the jQuery.tmpl.tag map.

Using the {{tmpl}} Template Tag

The following example shows how to use {{tmpl}} to render a nested template.

<script id="movieTemplate" type="text/x-jquery-tmpl"> 
    {{tmpl "#titleTemplate"}}
    <tr class="detail"><td>Director: ${Director}</td></tr>
</script>

<script id="titleTemplate" type="text/x-jquery-tmpl"> 
    <tr class="title"><td>${Name}</td></tr>
</script>

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 following example shows how to iterate over hierarchical data, by passing a data parameter to the a nested {{tmpl}} tag.

Templates:
<script id="movieTemplate" type="text/x-jquery-tmpl"> 
    <tr>
        <td>${Name}</td>
        <td>{{tmpl(Languages) "#languageTemplate"}}</td>
    </tr>
</script>

<script id="languageTemplate" type="text/x-jquery-tmpl"> 
    <em>${Name}</em>
</script>
Data:
var movies = [
    { Name: "Meet Joe Black", Languages: ["English", "French"] },
    { Name: "The Mighty", Languages: ["English"] },
    { Name: "City Hunter", Languages: ["Mandarin", "Cantonese"] }
];

Recursive Nested {{tmpl}} Tags

A template may contain a {{tmpl}} or {{wrap}} tag referencing the same template. The following example uses a recursive template to create a tree view:

Templates:
<script id="folderTmpl" type="text/x-jquery-tmpl">
    <li class="toggle">
        <span class="expand">${expanderSymbol($item)}</span>
        <span>${name}</span>
    </li>
    {{if expanded}}
        <li>
            <ul>{{tmpl(getFolderItems($item)) "#itemTmpl"}}</ul>
            <ul>{{tmpl(getSubFolders($item)) "#folderTmpl"}}</ul>
        </li>
    {{/if}}
</script>

<script id="itemTmpl" type="text/x-jquery-tmpl">
    <li class="folderItem">${name}</li>
</script>
Data:
// Hierarchy of named folders 
var folders = {
    name: "Samples",
    folders: [
        { name: "API", folders: [
            { name: ".tmpl()"}
        ]},
        { name: "Template markup", folders: [
            { name: "Tags", folders: [
                { name: "{{wrap}}"}
            ]},
        ]},
    ]
};

// Array for the folder items. Each item can show up in one or more folders
var samples = [
    { name: "Template in script block", 
        folders: [ ".tmpl()" ], 
        description: "Rendering a template declared in script block" },
    { name: "Tab View", 
        folders: [ "{{wrap}}", ".tmpl()" ], 
        description: "A tab view, using {{wrap}}" }
];

Note:

This feature and its documentation are in beta and subject to change before final release.
  • Using {{tmpl}} to render a nested template.

    HTML:
    
    <tmpl id="movieTemplate" type="text/x-jquery-tmpl"> 
        {{tmpl "#titleTemplate"}}
        <tr class="detail"><td>Director: ${Director}</td></tr>
    </tmpl>
    
    <tmpl id="titleTemplate" type="text/x-jquery-tmpl"> 
        <tr class="title"><td>${Name}</td></tr>
    </tmpl>
    
    <table><tbody id="movieList"></tbody></table>
    
    CSS:
    
    table { border-collapse:collapse; border:2px solid blue; margin:5px; background-color:#f8f8f8; }
    table tr { border:1px solid blue; } table td { padding:2px; }
    .title { border-bottom:none; } .detail { border-top:none; }
    
    Code:
    
    var movies = [
        { Name: "The Red Violin", Director: "François Girard" },
        { Name: "Eyes Wide Shut", Director: "Stanley Kubrick" },
        { Name: "The Inheritance", Director: "Mauro Bolognini" }
    ];
    
    /* Render the template with the movies data */
    $( "#movieTemplate" ).tmpl( movies ).appendTo( "#movieList" );
    
  • Using {{tmpl}} to render hierarchical data.

    HTML:
    
    <tmpl id="movieTemplate" type="text/x-jquery-tmpl"> 
        <tr>
            <td>${Name}</td>
            <td>{{tmpl(Languages.results) "#languageTemplate"}}</td>
        </tr>
    </tmpl>
    
    <tmpl id="languageTemplate" type="text/x-jquery-tmpl"> 
        <em>${Name} </em>
    </tmpl>
    
    <table><tbody><tr><th>Title</th><th>Languages</th></tr></tbody>
    <tbody id="movieList"></tbody></table>
    <button id="foreignBtn">Foreign</button>
    <button id="dramaBtn">Drama</button>
    
    CSS:
    
    table {float:left;clear:right;border-collapse:collapse;width:370px;background-color:#f8f8f8;margin:4px;} table td {border:1px solid blue;padding:3px;}
    table th {font-weight:bold;border:2px solid blue;padding:1px;} table tbody {border:2px solid blue;} button {float:left;margin:4px;width:70px;}
    
    Code:
    
    function getMovies( genre, skip, top ) {
        $.ajax({
            dataType: "jsonp",
            url: "http://odata.netflix.com/Catalog/Genres('" + genre
                + "')/Titles?$format=json&$expand=Languages&$skip="
                + skip + "&$top=" + top,
            jsonp: "$callback",
            success: function( data ) {
                /* Get the movies array from the data */
                var movies = data.d.results;
    
                /* Remove current set of movie template items */
                $( "#movieList" ).empty();
                
                /* Render the template with the movies data and insert
                   the rendered HTML under the "movieList" element */
                $( "#movieTemplate" ).tmpl( movies )
                    .appendTo( "#movieList" );
            }
        });
    }
    
    $( "#foreignBtn" ).click( function() {
        getMovies( "Foreign", 0, 4 );
    });
    
    $( "#dramaBtn" ).click( function() {
        getMovies( "Drama", 0, 4 );
    });
    
  • Using the options parameter of the {{tmpl}} tag to provide a showLanguage method.

    HTML:
    
    <tmpl id="movieTemplate" type="text/x-jquery-tmpl"> 
        <tr>
            <td>${Name}</td>
            <td>{{tmpl(Languages.results, $item.languageOptions) "#languageTemplate"}}</td>
        </tr>
    </tmpl>
    
    <tmpl id="languageTemplate" type="text/x-jquery-tmpl"> 
        <em>${$item.showLanguage(Name)} </em>
    </tmpl>
    
    <table><tbody><tr><th>Title</th><th>Languages</th></tr></tbody>
    <tbody id="movieList"></tbody></table>
    <button id="foreignBtn">Foreign</button>
    <button id="dramaBtn">Drama</button>
    
    CSS:
    
    table {float:left;clear:right;border-collapse:collapse;width:370px;background-color:#f8f8f8;margin:4px;} table td {border:1px solid blue;padding:3px;}
    table th {font-weight:bold;border:2px solid blue;padding:1px;} table tbody {border:2px solid blue;} button {float:left;margin:4px;width:70px;}
    
    Code:
    
    function getMovies( genre, skip, top ) {
        $.ajax({
            dataType: "jsonp",
            url: "http://odata.netflix.com/Catalog/Genres('" + genre
                + "')/Titles?$format=json&$expand=Languages&$skip="
                + skip + "&$top=" + top,
            jsonp: "$callback",
            success: function( data ) {
                /* Get the movies array from the data */
                var movies = data.d.results;
    
                /* Remove current set of movie template items */
                $( "#movieList" ).empty();
    
                /* Render the template items for each movie.
                   Pass in the languageOptions map which will be used as
                   options parameter on the nested "languageTemplate" template.
                   The 'showLanguage' method will be called by the nested template. */
                $( "#movieTemplate" ).tmpl( movies, {
                    languageOptions: {
                        showLanguage: function showLanguage( name ) {
                            return name.toUpperCase();
                        }
                    }
                }).appendTo( "#movieList" );
            }
        });
    }
    
    $( "#foreignBtn" ).click( function() {
        getMovies( "Foreign", 0, 4 );
    });
    
    $( "#dramaBtn" ).click( function() {
        getMovies( "Drama", 0, 4 );
    });
    
  • A tree view, using recursive nested {{tmpl}} tags.

    HTML:
    
    <tmpl id="folderTmpl" type="text/x-jquery-tmpl">
        <li class="toggle">
            <span class="expand">${expanderSymbol($item)}</span>
            <span>${name}</span>
        </li>
        {{if expanded}}
            <li>
                <ul>{{tmpl(getFolderItems($item)) "#itemTmpl"}}</ul>
                <ul>{{tmpl(getSubFolders($item)) "#folderTmpl"}}</ul>
            </li>
        {{/if}}
    </tmpl>
    
    <tmpl id="itemTmpl" type="text/x-jquery-tmpl">
        <li class="folderItem">${name}</li>
    </tmpl>
    
    <ul id="samplesList" class="treeView"><li></li></ul>
    
    CSS:
    
    .treeView li li {margin-left:18px;} .expand {vertical-align:middle;margin-right:7px;display:inline-block;border:1px solid #555;text-align:center;height:12px;width:12px;line-height:11px;background-color:#f8f8f8;color:Blue;} 
    .treeView, .treeView ul {padding:0;margin:0;} .treeView li {margin-left:8px;list-style-type:none;padding:2px;cursor:pointer;} .treeView li.folderItem {color:Blue;text-decoration:underline;font-style:italic;margin-bottom:4px;}
    
    Code:
    
     /* Hierarchy of named folders */ 
    var folders = {
        name: "Samples",
        folders: [
            { name: "API", folders: [
                { name: ".tmpl()"}
            ]},
            { name: "Template markup", folders: [
                { name: "Tags", folders: [
                    { name: "{{wrap}}"}
                ]},
            ]},
        ]
    };
    
    /* Array for the folder items. Each item can show up in one or more folders */
    var samples = [
        { name: "Template in script block", 
            folders: [ ".tmpl()" ], 
            description: "Rendering a template declared in script block" },
        { name: "Template as string", 
            folders: [ ".tmpl()" ], 
            description:"Rendering a template passed as a string" },
        { name: "Render remote data", 
            folders: [ "API" ], 
            description: "Rendering remote data using templates" },
        { name: "Tab View", 
            folders: [ "{{wrap}}", ".tmpl()" ], 
            description: "A tab view, using {{wrap}}" }
    ];
    
    /* Declare the functions for getting the items and subfolders, etc. 
       These could be simple global functions. 
       (Here we are adding them to the window object, which is equivalent). */
    $.extend( window, { 
        getFolderItems: function( tmplItem ) {
            return $.map( samples, function( sample ) {
                return $.inArray( tmplItem.data.name, sample.folders ) > -1 ? sample : null;
            });
        }, 
        getSubFolders: function( tmplItem ) {
            return tmplItem.data.folders || [];
        }, 
        expanderSymbol: function( tmplItem ) {
            return tmplItem.data.expanded ? "-" : "+";
        }
    });
    
    $( "#folderTmpl" ).tmpl( folders ).appendTo( "#samplesList" );
    
    $( "#samplesList" )
        .delegate( ".toggle", "click", function() {
            /* Toggle expanded property on data, then update rendering */
            var tmplItem = $.tmplItem( this );
            tmplItem.data.expanded = !tmplItem.data.expanded;
            tmplItem.update();
        })
        .delegate( ".folderItem", "click", function() {
            alert( $.tmplItem( this ).data.description );
        });