Backbone table view consuming row view - how to structure?

橙三吉。 提交于 2020-01-01 04:29:13

问题


I have a collection of models that I wish to render in a table view. Each model should be represented by a single row in the table, and this row should be generated using a template. I should be able to attach event handlers to that row (say click), that upon event alert some specific information regarding the model associated with that row.

A common way I've seen similar things to this done is to break each row out into it's own view, and have a parent view (lets say the table in this case) use the row view to generate the html to include in your code. However I can't figure out how this works with templates.

In this case, I can not attach events specifically to the RowView as it has no reference to a dom element (this.el for backbone), it simply returns a string. How can I achieve what I want, whilst using a template to maximum capacity?

The question isn't specifically about events, templating or using nested views, but more about the right way to use Backbone to achieve this kind of output.

Sample code(also in a fiddle):

/** View representing a table */
var TableView = Backbone.View.extend({
    tagName: 'table',
    render: function() {
        var rows = _.map(this.collection.models, function(p) {
            return new RowView({model: p}).render();                        
        });
        $('body').html(this.$el.html(rows.join('')));
    }
});

/** View representing a row of that table */
var RowView = Backbone.View.extend({
    render: function() {
        // imagine this is going through a template, but for now
        // lets just return straight html.
        return '<tr>' + 
                '<td>' + this.model.get('name') + '</td>' + 
                '<td>' + this.model.get('age') + '</td>' +
               '</tr>';
    }
});

var data = [
    {'name': 'Oli', 'age': 25},
    {'name': 'Sarah', 'age': 20}];

/** Collection of models to draw */
var peopleCollection = new Backbone.Collection(data);
var tableView = new TableView({collection: peopleCollection});
tableView.render();

Thank you!


回答1:


One way to handle a hierarchy of views is to have each view render its children and append them to its el . The events are then handled by each view, according to its model/collection.

To inject your HTML as the view el and thus control the container element, you can use the setElement method

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.

Your example could be rewritten as

var rowTemplate=_.template("<tr>"+
     "<td class='name'><%= name %></td>"+
     "<td class='age'><%= age %></td>"+
     "</tr>");

/** View representing a table */
var TableView = Backbone.View.extend({
    tagName: 'table',

    initialize : function() {
        _.bindAll(this,'render','renderOne');
    },
    render: function() {
        this.collection.each(this.renderOne);
        return this;
    },
    renderOne : function(model) {
        var row=new RowView({model:model});
        this.$el.append(row.render().$el);
        return this;
    }
});

/** View representing a row of that table */
var RowView = Backbone.View.extend({  
    events: {
        "click .age": function() {console.log(this.model.get("name"));}
    },

    render: function() {
        var html=rowTemplate(this.model.toJSON());
        this.setElement( $(html) );
        return this;
    }
});

var data = [
    {'name': 'Oli', 'age': 25},
    {'name': 'Sarah', 'age': 20}];

/** Collection of models to draw */
var peopleCollection = new Backbone.Collection(data);
var tableView = new TableView({collection: peopleCollection});
$("body").append( tableView.render().$el );

And a Fiddle http://jsfiddle.net/9avm6/5/



来源:https://stackoverflow.com/questions/10328687/backbone-table-view-consuming-row-view-how-to-structure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!