Use only template to build backbone view

193 views Asked by At
var ItemView = Backbone.View.extend({
    tagName:"li",
    className:"l-item",
    template:_.template("#tpl-list-item"),
    .....
});

var ListView  = Backbone.View.extend({
    render:(){
        this.collection.each(function(model){
            this.$el.append(new ItemView({model:model}).render().$el);
        });
    }
});

<script id="tpl-list-item" type="text/template">
    <div>
        // other markup
    <div>
</script>

As shown once I want to update the representation of the itemview, I will have to check both the js and the template file.

And I prefer to build the view from the template only to avoid set the representation in the code like :

<script id="tpl-list-item" type="text/template">
    <li class="....">
        <div>
            // other markup
        <div>
    </li>
</script>

Is this possible?

3

There are 3 answers

0
mu is too short On BEST ANSWER

You could use setElement to replace the view's el:

setElement view.setElement(element)

If you'd like to apply a Backbone view to a different DOM element, use setElement, which will also create the cached $el reference and move the view's delegated events from the old element to the new one.

In practice, it would look something like this:

var ItemView = Backbone.View.extend({
    template: _.template("#tpl-list-item"),
    render: function() {
        this.setElement(this.template(this.model.toJSON()));
        return this;
    },
    //...
});

and ListView wouldn't need to change.

Demo: https://jsfiddle.net/ambiguous/fs9h6o09/

This approach will end up creating and throwing away a bunch of <div> nodes as the view will create empty <div>s as the el if you don't tell it to do something else via id, className, ... properties. These extra <div>s probably won't make any noticeable difference but you could use some el: '#no-such-id' trickery to avoid them.

Backbone doesn't set that much policy but it really does want to separate the el from what goes inside it. You don't have to follow this but you're going against the grain by doing it your way.

0
Ben Bud On

If I understand your question correctly you want to build a html directly from the template?

This is probably not a good idea. A view should handle the rendering of the template. Technically though you could do something like the following:

var ListView  = Backbone.View.extend({
    render: function(){
        var itemTemplate = "#tpl-list-item";
        this.collection.each(function(model){
            this.$el.append(_.template(itemTemplate,{item:model}));
        });
    }
});

The problem with doing this however is that now if itemTemplate needs to be modified it has no view to handle that logic. To make things as modular as possible you are better off rendering the template through its own view so that you can update/destroy the template however you please as a view. The purpose of the view is simple:

to organize your interface into logical views, backed by models, each of which can be updated independently when the model changes, without having to redraw the page. -Backbone.js

0
hashchange On

You can avoid using setTemplate(), ie creating and throwing away nodes for nothing, and still keep your view HTML all in one place, in the template.

Backbone.Decarative.Views provides you with a clean way to do this. For more, check out my answer here.