Массивная таблица вид потребляет вид строки - как структурировать?

У меня есть набор моделей, которые я хочу отобразить в виде таблицы. Каждая модель должна быть представлена ​​одной строкой в ​​таблице, и эта строка должна быть сгенерирована с использованием шаблона. Я должен уметь прикреплять обработчики событий к этой строке (например, щелчок), чтобы при событии оповещать о какой-то конкретной информации о модели, связанной с этой строкой.

Обычный способ, которым я видел подобные вещи, заключается в том, чтобы разбивать каждую строку на собственный вид и иметь родительский вид (скажем, таблицу в этом случае), используя представление строки для генерации html для включения в вашем коде. Однако я не могу понять, как это работает с шаблонами.

В этом случае я не могу привязывать события непосредственно к RowView, поскольку он не имеет ссылки на элемент dom (this.el для магистрали), он просто возвращает строку. Как я могу достичь того, что хочу, при использовании шаблона до максимальной емкости?

Вопрос не в частности о событиях, шаблонах или использовании вложенных представлений, а о правильном способе использования Backbone для достижения такого вида вывода.

Пример кода (также в 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();

Спасибо!

Ответ 1

Один из способов обработки иерархии представлений состоит в том, чтобы каждый вид отображал свои дочерние элементы и добавлял их к el. Затем события обрабатываются каждым представлением в соответствии с его моделью/коллекцией.

Чтобы внедрить ваш HTML в качестве представления el и, таким образом, управлять элементом контейнера, вы можете использовать метод setElement

setElement view.setElement(element)

Если вы хотите применить магистраль просмотрите другой элемент DOM, используйте setElement, который также будет создать кешированную ссылку $el и перенести делегированные представления от старого элемента до нового.

Ваш пример можно переписать как

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 );

И скрипт http://jsfiddle.net/9avm6/5/