0
votes

So I'm checking out the changes related to the latest backbone/underscore version. Prior I have a project running with BB 0.5.2 and underscore 1.1.7. I'm noticing something strange with regards to defining a template property within a view in the new version, which gives me reservations in going forward with upgrading.

In my current version I would define a view as such:

var MyView = Backbone.View.extend({
  template: _.template($('#exampleTemplate').html()),
  initialize: function() {...},
  render: function() { $(this.el).html(this.template(someObjectParam)); },
});

However, if I attempt to work in the same manner, using a simplified todo clone attempt as an example, I setup an html with an inline script template as such:

<script>
  $(document).ready(function() {
    app.init();
  });
</script>

<script type="text/template" id="itemViewTemplate">
  <div class="item">
    <input type="checkbox" name="isComplete" value="<%= item.value %>"/>
    <span class="description"><%= item.description %></span>
  </div>
</script>

In my included JS file I have:

var ItemView = Backbone.View.extend({   
  el: 'body',

  // Below causes error in underscore template, as the jquery object .html() call
  // returns null.  Commenting will allow script to work as expected.
  templateProp: _.template($('#itemViewTemplate').html()),  

  initialize: function() {
    // Same call to retrieve template html, returns expected template content.
    console.log($('#itemViewTemplate').html());  

    // Defining view template property inside here and calling it, 
    // properly renders.
    this.template = _.template($('#itemViewTemplate').html());
    this.$el.html(this.template({item: {value: 1, description: 'Something'}}));
  },
});

var app = {
  init: function() {
    console.log('Fire up the app');
    var itemView = new ItemView();
  }
}

So I'm left confused as to why defining the template property directly causes the call to retrieve the template html to return a null value, thus breaking the attempt to define an underscore template object (mouthful). However, if the definition is done within the initialize function, the call to retrieve the template html properly finds the template so its contents can be passed to the underscore template. Anyone see what I'm potentially missing?

Thanks in advance!

1
Interestingly, a direct copy and paste of the current TODO's backbone app, does not suffer from the same problem. Baffling. - aztechy

1 Answers

3
votes

If this:

var ItemView = Backbone.View.extend({   
  //...
  templateProp: _.template($('#itemViewTemplate').html()),
  //...
});

is failing because $('#itemViewTemplate').html() is null, then you have a simple timing problem: you're trying to read the content of #itemViewTemplate before it exists. Your old version should suffer from exactly the same problem.

Either make sure everything is loaded in the right order (i.e. your views after your template <script>s) or compile the template in your view's initialize. You can check for the templateProp in your view's prototype and only compile it on first use if you want:

initialize: function() {
    if(!this.constructor.prototype.template)
        this.constructor.prototype.template = _.template($('#itemViewTemplate').html());
    //...
}

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