ironchicken
ironchicken

Reputation: 794

Accessing model attributes from Backbone view Underscore template

I have a Backbone.js view that looks like this:

var StreamV = Backbone.View.extend({
    tagName: 'div',
    className: 'stream',
    events: { },
    initialize: function () {
        this.listenTo(this.model, 'change', this.render);
    },
    render: function () {
        this.$el.html(this.template(this.model.attributes));
        return this;
    },
    template: function (data) {
        console.log(data);
        if (data.mime_type.match(/^audio\//)) {
            return _.template('<audio controls><source src="<%= resource_uri %>">No sound</audio>', data);
        } else {
            // FIXME Do what?
            return _.template();
        }
    },
});

With a corresponding model that looks like this:

var StreamM = Backbone.Model.extend({
    url: function () {
        return (this.id) ? '/streams/' + this.id : '/streams';
    }
});

And I'm trying to instantiate the StreamV view like this:

$(document).ready(function () {
    var streams = new StreamsC;
    streams.fetch({success: function (coll, resp, opts) {
        var mp3 = coll.findWhere({mime_type: 'audio/mp3'});
        if (mp3) {
            var mp3view = new StreamV({el: $('#streams'),
                                       model: mp3});
            mp3view.render();
        } else {
            $('#streams').html('No audio/mp3 stream available.');
        }
    }});
});

I'm finding that my Underscore template is not picking up the data I'm sending it. It says:

ReferenceError: resource_uri is not defined
  ((__t=( resource_uri ))==null?'':__t)+

I've tried altering the _.template call to provide a literal object with the resource_uri property set and I get the same error.

Am I doing the right the thing by providing an object as the second argument to _.template?

Upvotes: 0

Views: 1575

Answers (1)

nordhagen
nordhagen

Reputation: 809

The Underscore template function returns a function to later be called with data. Its second argument is not the data to be inserted, but rather settings object.

From the Underscore docs:

var compiled = _.template("hello: <%= name %>");
compiled({name: 'moe'});
=> "hello: moe"

In your case you would first compile the template like so:

this.compiledTemplate = _.template('<audio controls><source src="<%= resource_uri %>">No sound</audio>');

Then later call this function with data when you are ready to render the view:

this.$el.html(this.compiledTemplate(this.model.toJSON()))

Upvotes: 1

Related Questions