Luke The Obscure
Luke The Obscure

Reputation: 1524

Loops in Mustache-Mode Underscore Templates

I've set underscore to mustache mode like so:

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

I've got part of a template with the following:

<script id="detail_view" type="text/template">
    <% for(registration in REGISTRATION_NUMBERS){ %>
        <tr>
            <td>{{registration.TYPE}}</td>
            <td>{{registration.VALUE}}</td>
        </tr>
<% } %>
</script>

Which results in "registration not defined". Using this causes the entire section to be output in the template. What am i doing wrong?

Upvotes: 1

Views: 1098

Answers (1)

mu is too short
mu is too short

Reputation: 434665

You have two problems, one you know about and one that you don't.

The first problem is that you're replacing all three _.templateSettings when you only want to replace one of them. You want this:

_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;

That will leave the evaluate and escape parts of _.templateSettings alone. What you're doing is the same as:

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

so you're ending up without an evaluate at all. BTW, you can look at the source property of a compiled template function to see the JavaScript that your template is compiled to, the JavaScript isn't that easy on the eyes but looking at it can help with this sort of problem.

The problem you don't know about is that a for...in loop is for iterating over the properties of an object, not the values in an array. This means that registration will be the strings '0', '1', ... inside your loop and that's not what you want. You'd need something like this in your template if REGISTRATION_NUMBERS is an array:

<% for(var i = 0; i < REGISTRATION_NUMBERS.length; ++i) { %>
    <% var registration = REGISTRATION_NUMBERS[i]; %>
    <tr>
        <td>{{registration.TYPE}}</td>
        <td>{{registration.VALUE}}</td>
    </tr>
<% } %>

Or, since you have Underscore around anyway, you could use _.each:

<% _(REGISTRATION_NUMBERS).each(function(r) { %>
    <tr>
        <td>{{r.TYPE}}</td>
        <td>{{r.VALUE}}</td>
    </tr>
<% }) %>

Demo: http://jsfiddle.net/ambiguous/jfckA/

Upvotes: 4

Related Questions