Search code examples
ruby-on-railsunderscore.jshamlinterpolationunderscore.js-templating

How to interpolate if/else statements with Underscore.js and HAML?


I'm trying to get if/else interpolate working with Underscore.js and HAML, but to no avail. I'm already changing the interpolate setting in Underscore.js to the following:

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

This works nicely when I'm trying to interpolate a value inside a notation like {{ value }}. However, I'm failing to make if/else statements work. I have the following:

{{ if (true) { }}
  {{ val }}
{{ } }}

I get an Javascript exception "Uncaught SyntaxError: Unexpected token if ". Help is much appreciated.


Solution

  • Underscore templates use three different sets of delimiters:

    1. evaluate: This is for bits of JavaScript, <% ... %> by default.
    2. interpolate: This is for dumping the contents of a variable, <%= ... %> by default.
    3. escape: As interpolate but also escapes HTML, <%- ... %> by default.

    These mostly match ERB syntax. You're trying to use the interpolation syntax with JavaScript that isn't an expression:

    {{ if(true) { }}
    

    but that won't work as an if isn't an expression in JavaScript.

    You probably want to override all three patterns:

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

    and then say things like this:

    {{ if (true) { }}
      {{= val }}
    {{ } }}
    

    If you can limit your templates to simple substitutions then you could just use interpolate and {{expr}} in your templates.