Cómo mostrar CompositeView con vista de varios hijos en Backbone Marionette

El problema inicial

Tengo una vista compuesta (una tabla) para la cual cada model en la colección se representa como dos filas de la tabla, con una plantilla como:

<tr class="row-parent"> <td>parent info here</td> </tr> <tr class="row-child"> <td>child info here</td> </tr> 

Con un ItemView como este:

 var ItemView = Backbone.Marionette.ItemView.extend({ template: ItemTmpl }); 

Aunque se denominan 'padre' y 'hijo', en realidad son miembros del mismo model. Si no especifico un tagName, Backbone ajustará cada vista en un <div> que es tanto HTML no válido como también rompe el layout.

El primer bash de una solución

Así que pensé, ¿por qué no eliminar las tags externas <tr> y dejar que Backbone las agregue? Así que actualicé mi plantilla para que fuera así:

  <td>parent info here</td> </tr> <tr class="row-child"> <td>child info here</td> 

Y actualizó la vista para:

 var ItemView = Backbone.Marionette.ItemView.extend({ template: ItemTmpl, tagName: 'tr', className: 'row-parent' }); 

Esperaba que una label externa se combinara con los fragments de tags interiores, pero a Marionette no le gustó eso. Solo mostró el hijo de la fila. Así que no estoy seguro de a dónde ir desde aquí. Estoy considerando dos estrategias, pero aún no he entrado en muchos detalles.

Avanzando: Plan A

Anula cualquier parte de Backbone que crea el div adicional para no crearlo, o anula la parte de Marionette que agrega la vista para eliminar el div justo antes de agregarlo.

Avanzando: Plan B

Cree un nuevo tipo de vista llamada CompositeMultiView que, naturalmente, se extendería fuera de CompositeView y les permitiría a ustedes dos especificar un segundo ItemView, o tal vez solo una matriz de vistas, todas las cuales se representarían para cada model dado. Este plan parece mucho más trabajo pero less pirateado.


¿Alguien tiene mejores sugerencias, soluciones provisionales o sugerencias concretas sobre cómo implementaría cualquiera de los dos planes anteriores?

Aquí hay una maqueta de cómo debería verse la tabla: enter image description here

Luché con el mismo problema hasta que finalmente descubrí que una tabla puede tener múltiples tags tbody , cada una con múltiples tags tr .

Esta es en realidad la respuesta proporcionada a una pregunta de columna vertebral similar.

Entonces su ItemView se convertiría en:

 var ItemView = Backbone.Marionette.ItemView.extend({ template: ItemTmpl, tagName: 'tbody' }); 

Y el html generado:

 <table> <!-- first item --> <tbody> <tr class="row-parent"> <td>parent info here</td> </tr> <tr class="row-child"> <td>child info here</td> </tr> </tbody> <!-- second item --> <tbody> <tr class="row-parent"> <td>parent info here</td> </tr> <tr class="row-child"> <td>child info here</td> </tr> </tbody> ... </table> 

Puede intentar modificar el CompositeView de la siguiente manera:

  1. Especifique itemView como una matriz de vistas
  2. Reemplazar addChildView para representar cada vista para cada model

Esta solución termina pareciéndose mucho a su "Plan B". Dale un tiro:

 itemView: [My.ParentView, My.ChildView], addChildView: function(item, collection, options){ this.closeEmptyView(); var itemViews = this.getItemView(item); var index = this.collection.indexOf(item); _.each(itemViews, function(ItemView) { this.addItemView(item, ItemView, index); }); } 

No he pensado si esto manejaría events model como destroy , pero creo que debería manejarlos con gracia.

Solución sucia: agregue una function de renderizado personalizada a su ItemView

 // Or whatever template you use var template = Handlebars.compile(datepickerTemplate); var ItemView = Backbone.Marionette.ItemView.extend({ render: function(){ var html = template(this.model.toJSON()); var newElement = $(html); this.$el.replaceWith(newElement); this.setElement(newElement); return this; } }); 

Esto debería eliminar el envoltorio div adicional