12

I'm trying to use handlebars style templating with underscore in backbone (with require.js). I have the following:

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

In my templates I have set up a test:

<div><%= title %> | {{ title }}</div>

I get the following in the browser:

Correct title | {{ title }}

So it looks like the standard underscore template settings are working and the handlebars style ones are getting ignored:

But if I check in the console in chrome I get this (which looks to me like it should be correct)

_.templateSettings
Object {evaluate: /<%([\s\S]+?)%>/g, interpolate: /\{\{(.+?)\}\}/g, escape: /<%-([\s\S]+?)%>/g}

Any ideas why this isn't working correctly?

mu is too short
  • 426,620
  • 70
  • 833
  • 800
jamie holliday
  • 1,617
  • 9
  • 26
  • 39

1 Answers1

20

When I do this:

_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;
var t = _.template($('#t').html());

with your template in #t, I get an error:

SyntaxError: Unexpected token '='

That nicely confirmed my suspicion that the evaluate regex:

/<%([\s\S]+?)%>/g

was matching your <%= ... %> in the template. An equals sign matches \S so of course the evaluate regex will find <%= ... %>, strip off the <% and %>, and leave you with a syntax error in the JavaScript that _.template will try to build.

If you look inside the _.template source you'll see that the regexes are checked in a particular order:

  1. escape
  2. interpolate
  3. evaluate

So just replacing interpolate will let the <%= ... %> things fall through to be caught (and misinterpreted) by evaluate.

All you need to do is replace the evaluate regex as well. I'd recommend replacing all three regexes to avoid problems:

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

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

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • Thanks. I've checked the demo and it all looks fine but i'm still getting the same result as before. The chrome console shows the correct settings but underscore is still using the old settings – jamie holliday Mar 27 '13 at 07:46
  • @jamieholliday: Sounds like a possible ordering problem. What's the difference between the jsfiddle.net demo and what you're doing? – mu is too short Mar 27 '13 at 15:43
  • 1
    Ok turns out it was an issue with the way I was loading in the settings. I am using require.js and this was causing an issue. Sovled the problem by using your regex and applying the setting as in here: http://stackoverflow.com/questions/13057330 – jamie holliday Mar 27 '13 at 19:19
  • Ahh, that makes sense. require.js can cause ordering problems. – mu is too short Mar 27 '13 at 20:00
  • 1
    @jamie holliday: In case you're using Marionette with the requirejs-tpl plugin (https://github.com/ZeeAgency/requirejs-tpl) consider adding templateSettings = _.templateSettings || { ... }; to line 26 of tpl.js ... This prevents the boogery override of this useful solution above in RequireJS environments. – 4Z4T4R Nov 16 '13 at 03:27
  • I found that the template strings needed to be like in this fiddle: http://jsfiddle.net/R4vpu/ – Brad Parks Mar 03 '14 at 18:57
  • @Brad: Seems that you're right, not sure how I missed that. Anything, I think they're right now, thanks for the heads up. – mu is too short Mar 03 '14 at 19:20
  • Thanks @muistooshort this saves my life :) in grunt processhtml template settings – Ajay Patel Jan 06 '17 at 18:01