2012-03-03 20 views
8

Tengo una vista llamada DashboardView que crea varias instancias WidgetView s. Cada widget necesita tener sus propios enlaces de eventos. Por lo que yo puedo decir, estos enlaces se pierden cuando la vista se representa y se añade a la vista padre, es decir:Eventos en vistas anidadas de Backbone.js

class DashboardView extends Backbone.View 
    constructor: -> 
    context = @ 
    _.each @collection, (w)-> 
     dv = new app.WidgetView(model: w) 
     context.$el.append(dv.render()) 

class WidgetView extends Backbone.View 
    events: 
    "click .config" : "config_widget" 

    render: -> 
     _.template($("#widget-template").html(), @model) 

Hacerlo de esta manera, los eventos de clic sobre el elemento .config del widget se han perdido . ¿Hay una mejor manera de mezclar las vistas anidadas en el elemento primario mientras se asegura que los controladores de eventos en la vista secundaria se canalicen correctamente?

Una solución que he visto para este problema viene en this article. Esto se ve bien, pero tengo curiosidad si hay una forma más elegante de resolver esto.

Respuesta

10

Prueba esto:

class DashboardView extends Backbone.View 
    constructor: -> 
    @collection.each (w) => 
     dv = new app.WidgetView(model: w) 
     @$el.append dv.render().el // Append widget's @el explicitly 

class WidgetView extends Backbone.View 
    tagName: 'div' // or whatever your view's root element is 

    template: _.template $("#widget-template").html() // pre-compile template 

    events: 
    "click .config": "config_widget" 

    render: -> 
    @$el.html @template @model.toJSON() // append template to @el 
    return this // return view 

Por lo tanto, la idea es la siguiente:

(1) Dentro de render método de la WidgetView 's, se rellenan de @el (el elemento raíz de la vista) con su modelo de datos a través de la plantilla. (Y note cómo puedo compilar la plantilla sola vez - no hay necesidad de compilar la plantilla en cada operación de procesamiento.)

(2) Dentro de la DashboardView, anexar elemento raíz del widget - @el - al DOM .

El hecho es que los eventos de la vista delegan en su elemento raíz - @el. Por lo tanto, desea trabajar explícitamente con el elemento raíz: dentro de render, lo rellena y luego lo agrega al DOM.

+0

Esto es exactamente lo que estaba buscando. ¡Gracias! – picardo

+4

Puede evitar las cosas 'context' utilizando [' (w) => '] (http://coffeescript.org/#fat_arrow). Y '@ collection' debe tener un subrayado ya que '@collection.each (w) =>' es otra opción. –

+0

@mu Cool ':)' No sabía acerca de la flecha adiposa. –

1

Su problema es que delegateEvents espera un elemento único y no cambiante para su vista. Como su función render crea un nuevo elemento cada vez, las vinculaciones realizadas por delegateEvents nunca se activan cuando hace clic en el elemento generado por render.

Afortunadamente, la versión actual de Backbone ofrece un setElement method que reasignará su elemento con el argumento que usted proporcione, y luego automáticamente llamará al delegateEvents.

+0

Una cosa que debería haber aclarado es que tengo varios widgets instanciados en un tablero. Así que reasignar el elemento no es exactamente lo que quiero, creo. – picardo

Cuestiones relacionadas