Reputation: 1881
I've been reading and researching, but I'm having trouble figuring out how to organize nested complex views for a Backbone/Marionette project. The answer in Two Collections inside a Composite View is very close to what I believe is needed, but it seems to fall short when it comes to handling multiple views in one of the collection items.
I'll explain by extending apartment example answer in that question.
Let's say we have a collection of apartments, a collection of their rooms, listing their chairs. In addition lets add in the apartment tenant. The idea being a tenant view could have it's own view management, events, and be reused elsewhere on the site.
From my understanding it might looks something like:
My problem being that the ApartmentView doesn't permit multiple sub views.
Copy of answer provided by @scott-puleo with addition of Tenants.
var apartments = [
{apartment: '1a',
rooms: [
{name: 'master bed', chairs: []},
{name: 'kitchen', chairs: [
{chairType: 'stool'}, {chairType: 'stool'}]},
{name: 'living room', chairs: [
{chairType: 'sofa'}, {chairType: 'love seat'}]}],
tenant:{name:Bob Jones,phone:6165551234}
},
{apartment: '2a',
rooms: [
{name: 'master bed', chairs: []},
{name: 'kitchen', chairs: [
{chairType: 'shaker'}, {chairType: 'shaker'}]},
{name: 'living room', chairs: [
{chairType: 'sectional'}]}]
tenant:{name:Hope Smith,phone:6365551234}
}];
var chairModel = Backbone.Model.extend({});
var roomModel = Backbone.Model.extend({
initialize: function(attributes, options) {
this.chairs = new Array();
_.each(attributes.chairs, function(chair){
this.chairs.push(new chairModel(chair));
}, this);
}
});
var ApartmentModel = Backbone.Model.extend({
initialize: function(attributes, options) {
this.rooms = new Array();
_.each(attributes.rooms, function(room){
this.rooms.push(new roomModel(room));
}, this);
}
});
var ApartmentCollection = Backbone.Collection.extend({
model: ApartmentModel
});
var ChairView = Backbone.Marionette.ItemView.extend({
template:'#chair'
});
var TenantView = Backbone.Marionette.ItemView.extend({
template:'#tenant'
});
var RoomView = Backbone.Marionette.CompositeView.extend({
template: '#room',
itemViewContainer: 'ul',
itemView: ChairView,
initialize: function(){
var chairs = this.model.get('chairs');
this.collection = new Backbone.Collection(chairs);
}
});
var ApartmentView = Backbone.Marionette.CompositeView.extend({
template: '#appartment',
itemViewContainer: 'ul',
itemView: RoomView, // Composite View
initialize: function(){
var rooms = this.model.get('rooms');
this.collection = new Backbone.Collection(rooms);
}
});
var ApartmentCollectionView = Backbone.Marionette.CollectionView.extend({
itemView: ApartmentView // Composite View
});
apartmentCollection = new ApartmentCollection(apartments);
apartmentCollectionView = new ApartmentCollectionView({
collection: apartmentCollection
});
App.apartments.show(apartmentCollectionView);
I feel I should be looking at initiating individual Layouts or Controllers for each of the Apartments, however can't be efficient, nor do I think that is what they are intended for. Those also might make it tricky to manage the ids in regions.
Thanks for any direction, I'll update with any answers I may uncover.
Upvotes: 4
Views: 3509
Reputation: 2925
Since Tenant is not separate backbone model, but part of Apartment, it is serialized and passed into ApartmentView, so it can be rendered directly.
Only change required for this to work is in template:
<script type="text/html" id="apartment">
<div>
<h2>Apartment: <%=apartment%></h2>
<ul></ul>
<b><%= tenant.name %>, <%= tenant.phone %></b>
</div>
</script>
Fiddle: http://jsfiddle.net/re7x2vas/
Upvotes: 0
Reputation: 1881
The answer I ended finding was to use LayoutViews, in this example for AppartmentView. LayoutViews extend ItemView and therefore use models as well. But in addition they support multiple regions that can then contain any sort of view (ItemView, CollectionView, CompositeView, LayoutView).
Basically, whenever you have a level that requires multiple sibling level views (regardless of type), they can be wrapped together in a LayoutView.
A quick note about events and communication between views as this quickly gets interesting. Marionette believes in top down event listening. That is a parent can listen to children, but children should be able to independently run and not need to listen to the parent.
So, when an event happens in a view that a sibling needs to react to - it is the parent that ought to listen for the child's event.. then trigger or call a function on the other child that needs to react.
Alternately a model at the parent level could be setup, then children can Set values and other views could listen for change events.
Your setup will very, but those are ideas to start with.
From my experience this is the breakdown of the different types of Marionette views:
Upvotes: 1