Vista de tabla de backbone consumiendo vista de fila – ¿cómo estructurar?

Tengo una colección de models que deseo mostrar en una vista de tabla. Cada model debe estar representado por una sola fila en la tabla, y esta fila debe generarse utilizando una plantilla. Debería ser capaz de adjuntar manejadores de events a esa fila (por ejemplo, hacer clic), que luego de un evento alertan sobre cierta información específica con respecto al model asociado con esa fila.

Una forma común en que he visto cosas similares a esto es dividir cada fila en su propia vista, y tener una vista principal (digamos la tabla en este caso) usar la vista de fila para generar el html para include en tu código . Sin embargo, no puedo entender cómo funciona esto con las templates.

En este caso, no puedo adjuntar events específicamente al RowView ya que no tiene reference a un elemento dom ( this.el for backbone), simplemente devuelve una cadena. ¿Cómo puedo lograr lo que quiero, mientras uso una plantilla a la capacidad máxima?

La pregunta no es específicamente sobre events, creación de templates o uso de vistas anidadas, sino más sobre la forma correcta de utilizar Backbone para lograr este tipo de resultados.

Código de muestra (también en un violín ):

 /** 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(); 

¡Gracias!

Una forma de manejar una jerarquía de vistas es hacer que cada vista represente sus hijos y los agregue a su el . Los events son manejados por cada vista, de acuerdo con su model / colección.

Para inyectar su HTML como view el y controlar así el elemento del contenedor, puede usar el método setElement

setElement view.setElement(element)

Si desea aplicar una vista Backbone a un elemento DOM diferente, use setElement, que también creará la reference $ el en caching y moverá los events delegates de la vista desde el elemento anterior al nuevo.

Tu ejemplo podría ser reescrito como

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

Y un violín http://jsfiddle.net/9avm6/5/