2012-04-26 4 views
10

私はテーブルビューでレンダリングしたいモデルのコレクションを持っています。各モデルは表内の単一の行で表され、この行はテンプレートを使用して生成される必要があります。イベントハンドラをその行に付け加えることができます。イベントハンドラは、その行に関連付けられたモデルに関する特定の情報を警告します。バックボーン・テーブル・ビューはロー・ビューを消費します - どのように構造化しますか?

これと同様のことを私が見てきた一般的なやり方は、各行をそれ自身のビューに分割し、親ビュー(この場合はテーブルを言う)を使用してhtmlを生成する行ビューを使用することです。あなたのコードにインクルードしてください。しかし、私はテンプレートでどのように動作するのか把握できません。

この場合、dom要素(バックボーンの場合はthis.el)への参照がないため、イベントをRowViewに特別に付加することはできません。単に文字列を返します。どのようにして最大限の容量にテンプレートを使用しながら私が望むものを達成することができますか?

質問はイベント、テンプレート、またはネストされたビューを使用したものではありませんが、バックボーンを使ってこのような出力を実現する方法については詳しく説明しています。 (もfiddle中)

サンプルコード:

/** View representing a table */ 
var TableView = Backbone.View.extend({ 
    tagName: 'table', 
    render: function() { 
     var rows = _.map(this.collection.models, function(p) { 
      return new RowView({model: p}).render();       
     }); 
     $('body').html(this.$el.html(rows.join(''))); 
    } 
}); 

/** View representing a row of that table */ 
var RowView = Backbone.View.extend({ 
    render: function() { 
     // imagine this is going through a template, but for now 
     // lets just return straight html. 
     return '<tr>' + 
       '<td>' + this.model.get('name') + '</td>' + 
       '<td>' + this.model.get('age') + '</td>' + 
       '</tr>'; 
    } 
}); 

var data = [ 
    {'name': 'Oli', 'age': 25}, 
    {'name': 'Sarah', 'age': 20}]; 

/** Collection of models to draw */ 
var peopleCollection = new Backbone.Collection(data); 
var tableView = new TableView({collection: peopleCollection}); 
tableView.render(); 

ありがとうございます!

答えて

11

ビューの階層を処理する1つの方法は、各ビューに子をレンダリングし、その子をelに追加させることです。イベントは、モデル/コレクションに従って各ビューで処理されます。あなたがバックボーン ビューを適用したい場合は

ビューelとしてあなたのHTMLを注入し、これコンテナ要素を制御するには、setElement方法

のsetElementview.setElement(element)

を使用することができます別のDOM要素にsetElementを使用してください。 キャッシュされた$ el参照を作成し、ビューの委譲されたイベント を古い要素から新しいものに移動します。

あなたの例では、

var rowTemplate=_.template("<tr>"+ 
    "<td class='name'><%= name %></td>"+ 
    "<td class='age'><%= age %></td>"+ 
    "</tr>"); 

/** View representing a table */ 
var TableView = Backbone.View.extend({ 
    tagName: 'table', 

    initialize : function() { 
     _.bindAll(this,'render','renderOne'); 
    }, 
    render: function() { 
     this.collection.each(this.renderOne); 
     return this; 
    }, 
    renderOne : function(model) { 
     var row=new RowView({model:model}); 
     this.$el.append(row.render().$el); 
     return this; 
    } 
}); 

/** View representing a row of that table */ 
var RowView = Backbone.View.extend({ 
    events: { 
     "click .age": function() {console.log(this.model.get("name"));} 
    }, 

    render: function() { 
     var html=rowTemplate(this.model.toJSON()); 
     this.setElement($(html)); 
     return this; 
    } 
}); 

var data = [ 
    {'name': 'Oli', 'age': 25}, 
    {'name': 'Sarah', 'age': 20}]; 

/** Collection of models to draw */ 
var peopleCollection = new Backbone.Collection(data); 
var tableView = new TableView({collection: peopleCollection}); 
$("body").append(tableView.render().$el); 

とフィドルhttp://jsfiddle.net/9avm6/5/

+0

のように書き換えることができ 'setElement'は、私が行方不明になってのだ作品だった - ありがとう! –

+0

素晴らしい。 1つの質問、あなたは_bindAll呼び出しを詳しく説明できますか?関数が呼び出された時点で 'this'をより有用にするはずですが、その形式の呼び出しはどういう意味ですか?レンダリングとrenderOneをどのイベントにバインドしていますか? renderOneを何にバインドするのですか?本当にありがとう! – Nicolas78

+0

@ Nicolas78 _.bindAllは、renderやrenderOneの 'this'がビューであり、イベントをトリガした要素ではないことを保証します。ここではあまり役に立ちませんが、バインディングは設定されていませんが、collection.resetではレンダー、collection.addではrenderOneを呼び出すことができます。 – nikoshr

関連する問題