underscore.js nested templates

ragulka picture ragulka · Jan 20, 2012 · Viewed 19.7k times · Source

Is it possible to somehow take a DOM element from a underscore template and use it as another template?

The idea is that my app needs to render a document that contains a loop with items and a summary. I need to occasionaly re-render only the summary or a few items, so I cannot just re-render the whole document.

However, I would like to keep it simple for the app users to create their own templates for the document and I think that keeping everything in one file for a document would make it easier.

I'm trying to use something like this:

<script type="text/template" id="document-template">
    <div id="document">
        <h1><%= name %></h1>
        <ul class="items">
            <% _.each(items, function(item) { %> 
                <li><%= item %></li>
            <% }); %>
        </ul>
        <div id="summary">
            <p>Total items: <%= totalitems %></p>
        </div>
    </div>
</script>

Now, I can easily do this var documentTemplate = _.template($('#document-template').html()); to turn this into a document template, but I would like to turn the summary part into a template and a list item into a template as well.

Can I do something like this:

var summaryTemplate = _.template($('#document-template #summary').html());
var itemTemplate = _.template($('#document-template .items li').html());

PS. Actually I am loading the template from an external file using jQuery's $.get. This way I will get the document-template in one big string. From there, I can do just documentTemplate = _.template(loadedString);.

Now, if I could just extract the #summary element from the string, it should work. But when I try to convert the string to DOM element ( var domElement = $(loadedString)) (so I could do this: summaryTemplate = _.template($('#summary',domElement).html());, it won't work, because underscore won't recognize the <%= %> tags anymore.

Answer

Jon z picture Jon z · Nov 30, 2012

You can pass the nested template as a variable in the template assignments to the main template, e.g.:

HTML:

<script type="text/template" id="sub_template">
  <article>
    <h1>id: <%= id %><h1>
  </article>
</script>

<script type="text/template" id="main_template">
  <% for (var i = 0; i < num; i++) { %>
    <%= renderSub({id:i}) %>
  <% } %>
</script>

JS:

 var renderSub = _.template( $('#sub_template').remove().text() ),
     renderMain = _.template( $('#main_template').remove().text() );

  renderMain({num:5, renderSub:renderSub});