2012-03-03 2 views
8

У меня есть вид, называемый DashboardView, который создает несколько WidgetView s. Каждый виджет должен иметь собственные привязки событий. Насколько я могу судить, эти привязки теряются, когда представление оказывается и добавил к родительскому мнению, а именно:События в 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) 

Делая это таким образом, что события кликов на .config элемент виджета теперь потеряны , Есть ли лучший способ смешивания вложенных представлений в родительском объекте, гарантируя, что обработчики событий на дочернем представлении правильно настроены?

Одно из решений, которое я видел в этой проблеме, - this article. Это выглядит правильно, но мне любопытно, есть ли более элегантный способ решения этого.

ответ

10

Попробуйте это:

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 

Таким образом, идея заключается в следующем:

(1) Внутри render метода WidgetView «s, вы заселить @el (корневой элемент представления) с его модели данных через шаблон. (И заметьте, как компилировать шаблон только один раз - нет необходимости компилировать шаблон на каждой визуализации операции.)

(2) Внутри DashboardView, вы добавляете виджета корневой элемент - @el - в DOM ,

Дело в том, что события представления делегируют его корневому элементу - @el. Поэтому вы хотите явно работать с корневым элементом: внутри render вы заполняете его, а затем добавляете его в DOM.

+0

Это именно то, что я искал. Спасибо! – picardo

+4

Вы можете избежать «контекста», используя ['(w) =>'] (http://coffeescript.org/#fat_arrow). И '@ collection' должен быть Underscore-ified уже так:' @collection.each (w) => 'это еще один вариант. –

+0

@mu Cool ':)' Не знал про жирную стрелу. –

1

Ваша проблема заключается в том, что delegateEvents ожидает единого, неизменяемого элемента для вашего вида. Поскольку ваша функция render создает новый элемент каждый раз, привязки, сделанные delegateEvents, никогда не запускаются, когда вы нажимаете на элемент, сгенерированный render.

К счастью, текущая версия Backbone предлагает setElement method, который переназначает ваш элемент аргументом, который вы предоставляете, и затем он автоматически вызывает delegateEvents.

+0

Одна вещь, которую я должен был прояснить, заключается в том, что у меня есть несколько виджетов, созданных в одной панели. Я считаю, что переназначение элемента не совсем то, что я хочу. – picardo

Смежные вопросы