Search code examples
javascriptbackbone.jsunderscore.jsunderscore.js-templating

Underscore template throwing variable not defined error


I've watched some videos on the topic of backbone js. This is an example straight from the video. It is from 2012, so I'm thinking backbone rules/library have changed, but I can't figure out why this does not work at the moment. In the video, the person shows it running in the JS Fiddle, but I can't get it to work. (I've included the necessary libraries in JS Fiddle, i.e. underscore, backbone and jQuery)

var V = Backbone.View.extend({
  el:'body',
  render: function () {
  	var data = { lat: -27, lon: 153 };
    this.$el.html(_.template('<%= lat %> <%= lon%>', data));
    return this;
  }
});

var v = new V();

v.render();
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>


Solution

  • You used to be able to parse and fill in an Underscore template in one go like this:

    var html = _.template(template_string, data);
    

    But as of Underscore 1.7.0, the second argument to _.template contains template options:

    template _.template(templateString, [settings])

    Compiles JavaScript templates into functions that can be evaluated for rendering. [...] The settings argument should be a hash containing any _.templateSettings that should be overridden.

    You have to compile the template using _.template and then execute the returned function to get your filled in template:

    var tmpl = _.template(template_string);
    var html = tmpl(data);
    
    // or as a one-liner, note where all the parentheses are
    var html = _.template(template_string)(data);
    

    In your case, it would look something like this:

    var V = Backbone.View.extend({
      el:'body',
      render: function () {
        var data = { lat: -27, lon: 153 };
        var tmpl = _.template('<%= lat %> <%= lon %>');
        this.$el.html(tmpl(data));
        return this;
      }
    });
    
    var v = new V();
    
    v.render();
    <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
    
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script>