1対Nの関連を持つモデルのコレクションをMarionette.jsで表示する際のサンプルです。ちょっとイメージが湧きにくいので例を挙げると、以下のような感じです。
- クラス
- 生徒
- 生徒
- 生徒
- ・・・
- クラス
- 生徒
- 生徒
- 生徒
- ・・・
- ・・・
これをCollectionView,CompositeView,ItemViewを使用して描画します。それぞれのビューが対応するモデル,コレクションは以下の通りです。
- CollectionView : クラスのコレクション
- CompositeView : クラスモデル、生徒のコレクション
- ItemView : 生徒モデル
結果的にMariionette.jsなら簡単に描画できました。コード量がそこそこ多くなってますが、ほとんどがモデルの定義・生成部分であり、本質的なのはビューの定義の箇所だけです。
app.js
var Student = Backbone.Model.extend({}); var Students = Backbone.Collection.extend({ model: Student, }); var Class = Backbone.Model.extend({}); var Classes = Backbone.Collection.extend({ model: Class, }); var StudentView = Marionette.ItemView.extend({ tagName: 'li', template: '#template-student', }); var ClassView = Marionette.CompositeView.extend({ template: '#template-class', childView: StudentView, childViewContainer: 'ul', }); var ClassListView = Marionette.CollectionView.extend({ el: '#container', childView: ClassView, childViewOptions: function(model, index) { return { model: model, collection: model.get('collection'), childIndex: index, }; }, }); $(function() { var students1 = new Students([ new Student({ name: 'トム' }), new Student({ name: 'マイク' }), new Student({ name: 'レベッカ' }), ]); var students2 = new Students([ new Student({ name: 'ケン' }), new Student({ name: 'ルーシー' }), ]); var classes = new Classes([ new Class({ teacher: '山田', collection: students1 }), new Class({ teacher: '佐藤', collection: students2 }), ]); var classListView = new ClassListView({ collection: classes }); classListView.render(); });
index.html
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/underscore.js"></script> <script type="text/javascript" src="js/backbone.js"></script> <script type="text/javascript" src="js/backbone.marionette.js"></script> <script type="text/javascript" src="js/app.js"></script> </head> <body> <div id="container"></div> <script id="template-class" type="text/html"> <p>担任:<%= teacher %></p> <ul></ul> </script> <script id="template-student" type="text/html"> <%= name %> </script> </body> </html>
ポイントはapp.js
のchildViewOptions
です。単純にCompositeViewを使用する場合は特に難しいことはないのですが、CompositeViewがCollectionViewに描画される場合は、このようにchildViewOptions
で子供ビューに渡すmodel
,collection
を指定してあげないと上手くいきませんでした。(これに気付くのに結構ハマった・・・)
関連する記事
- 【tubetop】YouTubeの国別人気動画を自動集約するサイトを作ってみた
- Rails+JSフレームワークでリアルタイム掲示板を作成してみる(Backbone.js編)
- Rails+JSフレームワークでリアルタイム掲示板を作成してみる(Ember.js編)
- [rails] 特定のページのみで実行するJavascript
- パーシャルをrenderする際のパフォーマンスに関する注意点