Search code examples
javascriptunderscore.jstemplatingunderscore.js-templating

How to evaluate javascript functions in underscore with mustache notation?


I want to do something like this:

<script id="tmpl-books" type="text/template">
  <ul>
    <% for (var i = 0; i < books.length; i++) { %>
      <% var book = books[i]; %>
      <li>
      <em><%= book.title %></em> by <%= book.author %>
      </li>
    <% } %>
  </ul>
</script>

in my code, but I am using JSP so I have to use the {{ }} notation, but when I do this {{ for(var... }} does not work.

<script id="tmpl-books" type="text/template">
      <ul>
        {{ for (var i = 0; i < books.length; i++) { }}
          <% var book = books[i]; %>
          <li>
          <em>{{= book.title }}</em> by {{ book.author }}
          </li>
        {{ } }}
      </ul>
    </script>

How can I achieve this?


Solution

  • Underscore templates have three distinct regexes:

    Define an interpolate regex to match expressions that should be interpolated verbatim, an escape regex to match expressions that should be inserted after being HTML escaped, and an evaluate regex to match expressions that should be evaluated without insertion into the resulting string.

    If you want to use Handlebars-ish delimiters, you'll want to define all three rather than just the interpolate regex:

    _.templateSettings = {
        evaluate: /\{\{(.+?)\}\}/g,
        interpolate: /\{\{=(.+?)\}\}/g,
        escape: /\{\{-(.+?)\}\}/g
    };
    

    Also note that the interpolate and escape regexes must match things that evaluate won't due to the order that the regexes are applied in.

    With those template settings, a template like this:

    <script id="tmpl-books" type="text/template">
        <ul>
            {{ for (var i = 0; i < books.length; i++) { }}
                {{ var book = books[i]; }}
                <li>
                    <em>{{= book.title }}</em> by {{= book.author }}
               </li>
            {{ } }}
        </ul>
    </script>
    

    should work. Note the change from {{ book.author }} to {{= book.author }} since you're interpolating book.author, not evaluating it.