I have a use case where I want to have a collection of collectionViews (or composite views) rendered. What is the best way to do this using marionette.js?
My model structure is as follows-
A
|
|-- Collection<B>
|
|--Collection<C>
I want to render as follows -
A1
|
|--B1
| |
| C1
| |
| C2
| |
| C3
|
|--B2
|
C4
|
C5
|
C6
What is the best way to do this? I don't want it to be like this
A1
|
|--B1
| |
| |--C1
| |
| |--C2
| |
| |--C3
|
|--B2
|
|--C4
|
|--C5
|
|--C6
So you could achieve this by creating a collection view that can deiced if the child it is trying to display has a collection or if is just a model. So for this example i have set up a model which has a name and an optional collection, if the collection is used then it will contain a collection of models which in turn can have an optional collection.
Then define a collection view, the collection view will check if the child has a collection and it if does will use the collection view as the child.
//collection view that can choose to display another collection view or a model
myApp.Views.View1 = Marionette.CollectionView.extend({
tagName: "ul",
//overridden getChildView to return either another collection view or an item view
getChildView: function (child) {
if (child.get("collection")) {
return myApp.Views.View1;
}
return myApp.Views.ItemView;
},
//set either the collection or the model depending which view we are using
childViewOptions: function (model, index) {
if (model.get("collection")) {
return {
collection: model.get("collection"),
}
} else {
return {
model: model
}
}
}
});
if it doesn't then it will just use an item view to display the model
//item view to display final model
myApp.Views.ItemView = Marionette.ItemView.extend({
tagName: "li",
template: _.template('<%= name %>'),
})
here it is running - http://jsfiddle.net/leighking2/r5ogoL5h/
If you wanted to display the names of the models being render above the collection then you can use a composite view, this also allows us more control on hooking into the view to display the collection
//collection view that can choose to display another collection view or a model
myApp.Views.View1 = Marionette.CompositeView.extend({
tagName: "ul",
template: _.template('<li><%= name %></li><li><ul class="collectionHook"></ul></li>'),
childViewContainer: ".collectionHook",
//overridden getChildView to return either another collection view or an item view
getChildView: function (child) {
if (child.get("collection")) {
return myApp.Views.View1;
}
return myApp.Views.ItemView;
},
//set either the collection or the model depending which view we are using
childViewOptions: function (model, index) {
if (model.get("collection")) {
return {
model: model,
collection: model.get("collection"),
}
} else {
return {
model: model
}
}
}
});
http://jsfiddle.net/leighking2/kx9kuup0/
only issue is the html isn't 100% valid as you end up with a double <ul>
when you display a composite view inside a composite view but with some tweaking that could be fixed, it still renders correctly though.