Search code examples
javascriptbackbone.jsmarionetteunderscore.js-templating

Backbone templating approaches differences


I would like to understand about Backbone templating approaches. I’m using Marionette to deal with CollectionViews.

What is the difference to do this:

// This approach is working fine.

<script type="text/template" id="single-item">
    <li><strong><%= userName %></strong></li>
</script>

Instead of this:

<ul>
    each( Loop into each collection item ) :
        <li><%= item.property %></li>
    endEach;
</ul>

Solution

  • The Marionette CollectionView make a view instance per collection item. So you have the complete control over the item.

    Say you want to list users with a single view that handles all the list itself. It would look something like this:

    var UserList = Backbone.View.extend({
        template: _.template($('#user-list-template').html()),
        render: function(){
            this.$el.html(this.template({ users: this.collection.toJSON() }));
            return this;
        }
    });
    

    And the template

    <script type="text/template" id="user-list-template">
        <ul>
        <% _.each(users, function(user) { %>
            <li><%= user.email %></li>
        <% }) %>
        </ul>
    </script> 
    

    It's super simple and looks good from there.

    But then, you want to add an edit button for each user in the list. There begins the real problem with the approach above. You'd have to guess which element was clicked on, or put the user id in a data-id attribute in the template. All of that sucks.

    The CollectionView let you deal with that easily and everything is scoped to its sole responsibility.

    Make an item view:

    var UserListItem = Marionette.View.extend({
        template: _.template($('#user-list-item-template').html()),
        events: {
            'click @ui.edit': 'onEdit',
        },
        ui: {
            edit: '.edit-btn'
        },
        onEdit: function(e) {
            this.model.id; // the user model directly accessible
        }
    });
    

    With a super simple template.

    <script type="text/template" id="user-list-item-template">
        <li><%= user.email %> <button type="button" class="edit-btn">edit</button></li>
    </script>
    

    Then use it within your list view.

    var UserList = Marionette.CollectionView.extend({
        tagName: 'ul',
        childView: UserListItem
    });
    

    After that, adding features to your item view is really easy. It's even reusable in different list since the list and the item are decoupled.