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
を指定してあげないと上手くいきませんでした。(これに気付くのに結構ハマった・・・)