2013-02-21 3 views
0

Я показываю таблицу категорий с Backbone. Я создал два вида:Событие, инициированное во всех экземплярах Backbone.View

  • RowView (содержащие один Tr)
  • TableView (содержащий структуру таблицы)

Определения:

RowView = Backbone.View.extend({ 
    el: "#content table tbody", 
    initialize: function() { 
    this.render(); 
    }, 
    render: function(){ 
    var params = { name: this.model.get('name'), route: this.options.route }; 
    var template = _.template($("#rowTemplate").html(), params); 
    this.$el.append(template); 
    }, 
    events: { 
    "click #name": "clickHandler" 
    }, 
    clickHandler: function(event) { 
    console.log('Browse subcategories of ' + this.model.get('name')); 
    } 
}); 

TableView = Backbone.View.extend({ 
    el: "#content", 
    initialize: function(){ 
    this.render(); 
    }, 
    render: function(){ 
    var row = new this.collection(); 
    var that = this; 
    row.fetch({ 
     success: function() { 
     console.log('Collection fetch succeeded'); 
     var params = { title: that.options.title, 
         counter: row.at(0).get('counter'), 
         route: that.options.route 
        }; 

     var template = _.template($("#tableTemplate").html(), params); 
     that.$el.html(template); 
     // RowView's are created by iteration here 
     for(var x = 1; x < row.length; x++) { 
      var params = { model: row.at(x), route: that.options.route }; 
      var view = new RowView(params); 
     } 
     } 
    }); 
    } 
}); 

Как вы можете см., я добавил событие щелчка в RowView.

шаблон RowView:

<script type="text/template" id="rowTemplate"> 
<tr> 
    <td id="name" class="fill"><%= name %></td> 
    <td><a href="#<%= route %>/<%= name %>/edit" class="btn">Editar</a></td> 
</tr> 
</script> 

Нажатие любой #name запускает обработчик во всех экземпляра вида. Поэтому при нажатии одну категорию я получаю:

Browse subcategories of category1 127.0.0.1:68 
Browse subcategories of category2 127.0.0.1:68 
etc... 

Насколько я знаю, это потому, что все RowView's делегированы же el.

Первое, что я хотел сказать о добавлении category name к rowTemplate и сравнить значение в DOM со значением в представлении, чтобы увидеть, какой из них фактически вызывает событие.

Но эти решения выглядят действительно уродливо. Каков правильный способ сделать это в Backbone?

EXTRA: Является ли это лучше, если я создаю только один вид и повторяю в шаблоне, чтобы сгенерировать строки?

EDIT: Я думаю, что предоставленного кода достаточно. В противном случае я могу их добавить.

+2

«Нажатие любой #NAME вызывает ...» говорит о том, что вы дублируя 'id' атрибуты и это только легкий путь к ошибкам и путанице. –

+0

Измените их на классы ("click .fill": "clickHandler"). Но проблема сохраняется, вызывается каждый обработчик экземпляра. – jviotti

+0

Похоже, что все они используют один и тот же 'el' (' el: "#content table tbody"), так что, конечно, события запускаются в нескольких представлениях. –

ответ

1

вы можете изменить RowView так:

RowView = Backbone.View.extend({ 
    container: '#content table tbody', 
    tagName: 'tr', 
    initialize: function() { 
     this.render(); 
    }, 
    render: function() { 
     var params = { 
      name: this.model.get('name'), 
      route: this.options.route 
     }; 
     var template = _.template($("#rowTemplate").html(), params); 
     this.$el.html(template).appendTo(this.container); 
    }, 
    events: { 
     "click .fill": "clickHandler" 
    }, 
    clickHandler: function(event) { 
     console.log('Browse subcategories of ' + this.model.get('name')); 
    } 
}); 

и шаблон RowView:

<script type="text/template" id="rowTemplate"> 
<td class="fill"><%= name %></td> 
<td><a href="#<%= route %>/<%= name %>/edit" class="btn">Editar</a></td> 
</script> 

Backbone.js создаст tr элемент. затем this.$el.html(template).appendTo(this.container) введите tr элемент с шаблоном и добавьте в #content table tbody.

как раз так, события RowView должны быть делегированы на RowView's el, а не #content table tbody.

+0

Вы можете объяснить эту строку: это. $ El.html (шаблон) .appendTo (this.container) ;? почему это не this.container.append (шаблон); работает? – jviotti

+0

@jviotti Я только что закончил редактирование, пожалуйста, взгляните на него – anhulife

0

У вас есть более чем один элемент с тем же идентификатором на странице, из-за все ваши строки, имеющих элемент

<td id="name" class="fill">.

Идентификаторы элементов должны быть уникальными в документе.

Одним из решений было бы отличить строки в шаблоне и использовать события как функцию для установки правильного идентификатора.

Шаблон:

<script type="text/template" id="rowTemplate"> 
<tr> 
    <td id="name-<%= name %>" class="fill"><%= name %></td> 
    <td><a href="#<%= route %>/<%= name %>/edit" class="btn">Editar</a></td> 
</tr> 

События Функция:

events: function(){ 
    _events = {}; 
    _events["click #name-" + this.model.get('name')] = "clickHandler"; 
    return _events; 
} 
0

Попробуйте

RowView = Backbone.View.extend({ 
    container: '#content table tbody', 
    tagName: 'tr', 


    // initialize: function() { 
//   this.render(); 
//  }, 
    render: function() { 
     var params = { 
      name: this.model.get('name'), 
      route: this.options.route 
     }; 
     var template = _.template($("#rowTemplate").html(), params); 
     this.$el.append(this.template); 
    }, 
    events: { 
     "click .name": "clickHandler" 
    }, 
    clickHandler: function(event) { 
     console.log('Browse subcategories of ' + this.model.get('name')); 
    } 
}); 

шаблон RowView (нет необходимости для идентификации каждого представления строки):

<script type="text/template" id="rowTemplate"> 
<td class="name"><%= name %></td> 
<td><a href="#<%= route %>/<%= name %>/edit" class="btn">Editar</a></td> 
</script> 

Тогда табличное:

... 
     that.$el.html(template); 
     // RowView's are created by iteration here 
     for(var x = 1; x < row.length; x++) { 
      var params = { model: row.at(x), route: that.options.route }; 
      var view = new RowView(params); 
      that.$el.find('tbody').append(view.el); 
      view.render() 

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