Los eventos de backbone no se activan después de actualizar los eventos a través de fetch

Estoy usando backbone.marionette y tengo la siguiente combinación de CollectionView ItemView:

  PlansListItemView = PlansApp.ItemView.extend
    tagName: "tbody"
    template: "#plansRow"    
    events:
      'click th.expander': 'expandDocuments'

    expandDocuments: (e) =>
      # do stuff

  PlansCollectionView = PlansApp.CollectionView.extend
    tagName: "table"
    itemView: PlansListItemView 

Creo la vista a partir de una colección inicial de json que está incrustada en la página. Los eventos en el hash de eventos funcionan perfectamente.

Luego, en un evento de cambio desplegable, llamo a fetch() en la colección para recuperar una nueva colección de objetos. El DOM se reconstruye pero los controladores de eventos no se vuelven a conectar/

¿Alguien tiene idea de por qué puede pasar esto?

preguntado el 22 de mayo de 12 a las 15:05

¿Sus th tienen la clase "expansor" una vez que se reconstruye el DOM? -

@Brendan sí, las clases se especifican en la plantilla. -

¿Puedes publicar tu plantilla para la vista de elementos? el #plansRow? -

De acuerdo... Estaba pensando que la única razón por la que no funcionaría es porque jquery no pudo encontrar los selectores. Así que otra pregunta... Cuando renderizas por primera vez, ¿ves algún error en la consola? La razón por la que pregunto es porque recientemente nos encontramos con una situación en la que los clics no funcionaban y resultó que había un error. No estaba impidiendo el renderizado, pero las cosas simplemente no funcionaban. -

Se me acaba de ocurrir que una vez que vuelvas a renderizar, puedes hacer una llamada a delegarEvents para renovar los ganchos de eventos DOM. Intente eso y vea lo que sucede. -

1 Respuestas

Aunque no sé la causa exacta de inmediato, hay algunas cosas divertidas en su configuración que me hacen pensar que podría ser parte del problema.

NOTA: estoy haciendo algunas suposiciones ENORMES sobre su código y plantillas, según lo que ha publicado. Cualquier cantidad de cosas podrían estar sucediendo que invalidarían gran parte de lo que estoy diciendo. Sin embargo, dado lo que ha publicado, aquí están mis pensamientos sobre cómo organizaría este código, lo que puede ayudar a solucionar los problemas que está viendo.

¿Salida HTML incorrecta?

Su configuración de la vista de cada elemento como un <tbody> etiqueta, pero luego parece que tienes algunos <th> etiquetas representadas por esa vista, según el evento que haya configurado, al menos.

Esto va a producir HTML no válido, como:

<table>
  <tbody>
    <th></th>
  </tbody>
</table>

Es difícil decirlo sin ver la plantilla para #plansRow, pero supongo que algo así sale de esto.

El problema es que las vistas de colección no son buenas para generar tablas. Pueden generar filas dentro de una tabla perfectamente y un envoltorio de etiqueta de tabla, pero no podrán obtener los encabezados, el pie de página, el cuerpo u otras etiquetas de la tabla que necesita una buena estructura de tabla porque las vistas de colección no representan una plantilla de los suyos. Simplemente crean una etiqueta contenedora y luego representan a cada uno de los elementos secundarios de la colección.

Para corregir esto, use un CompositeView que es un CollectionView que también representa su propia plantilla.

Una mejor estructura de tabla con vistas compuestas

Una configuración más apropiada para construir tablas con Marionette es usar un CompositeView como padre y hacer que cada vista de elemento represente un tr etiqueta. Por ejemplo:


RowView = Backbone.Marionette.ItemView.extend({
  template: "#row-template",
  tagName: "tr"
});

TableView = Backbone.Marionette.CompositeView.extend({
  template: "#table-template",
  tagName: "table",

  appendHtml: function(cv, iv){
    cv.$("tbody").append(iv.el);
  }
});

Esto establecerá un <table> con la vista compuesta. La plantilla para esa vista contendría entonces el apropiado <thead><th>...</th></thead><tbody></tbody> etiquetas para definir la tabla.

La vista de fila se representa como una <tr> etiqueta, y se completa con los datos que necesita, incluido el apropiado <td> las etiquetas.

La appendHtml El método en la vista compuesta maneja la inserción de cada una de las vistas de elementos en el <tbody> etiqueta de la vista compuesta principal.

Puedes ver una versión en vivo de esto en este JSFiddle: http://jsfiddle.net/derickbailey/me4NK/

y una publicación de blog para acompañar este y otros usos de CompositeView, aquí: http://lostechies.com/derickbailey/2012/04/05/composite-views-tree-structures-tables-and-more/

contestado el 22 de mayo de 12 a las 18:05

Gracias por la respuesta detallada. Te dejaré saber cómo va. - dagda1

¡Totalmente en el clavo! La refactorización a la vista compuesta resolvió el problema sin llamar delegarEvents, que era mi siguiente opción. Ahora puedo ver cuándo usaría la vista compuesta, pero ¿cuándo usaría CollectionView o lo haría alguna vez? - dagda1

¡Me alegro de que haya funcionado! :) una vista de colección se usa cuando tienes una colección que no necesita un envoltorio externo a su alrededor. un simple <ul> es un buen ejemplo, porque la vista de colección puede tener su nombre de etiqueta establecido en "ul", luego puede representar cada vista de elemento como un "li" ... honestamente, no uso las vistas de colección muy a menudo. Sin embargo, son una parte necesaria de la marioneta, ya que proporcionan una base para vistas compuestas y son útiles en algunos escenarios: Derick Bailey

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.