Q1: Does the design make sense or is it any obvious flaws I should consider?
Design Assumptions: Collection A has many Model As, Model A has Collection of Model Bs, each Model B has it's own View B.
Q2: Possible to have a collection of ModelBs on each ModelA?
Answer: Doable.
It's fairly common for models to have a bunch of related sub-models "in" them. You can definitely go about it by creating (like you mention) an array, an object, a collection to hold those Model Bs (let's call it the container.) The basic way would be just to create the container and then instantiate new models and plug them in. Most likely you want some kind of reference in those Model Bs to the related parent Model A so that you can return to that state later. Like each Model B has a ModelA_ID as an attribute.
This might be a good use of Paul Uithol's Backbone-Relational.
With Backbone-Relational, you can setup your Model (class) and define it in such a way that it has a collection of Model Bs. Here is what the code looks like.
ModelA = Backbone.RelationalModel.extend({
relations: [{
type: Backbone.HasMany,
key: 'modelBs',
relatedModel: 'ModelB',
collectionType: 'ModelBCollection',
reverseRelation: {
key: 'parentA'
}
}],
defaults: ...,
initialize: ...,
etc. ... // Other instance properties and functions of model.
});
When you do this, every model A that you instantiate will have a collection of Model Bs that can be referenced through the ModelA attribute modelBs
. Or any key you designate.
Here is what it looks like to instantiate the ModelA.
myModelA = new ModelA({
// Setting up ModelA attributes...
'modelBs': [1, 3, 7]
});
I've instantiated the ModelA and along with setting the other attributes you may have defined, I'm also setting up the the value for attribute modelBs of ModelA. This is an array of ids of each ModelB that is related to ModelA. This is how your collection knows which ModelBs are associated to this ModelA.
myModelA.fetchRelated('modelBs');
Your .fetchRelated()
call sends a request to the server to populate the modelBs collection with ModelB 1, 3, and 7.
When you want to access the collection of ModelBs in ModelA, you would simply do something like this.
myModelA.get('modelBs');
This returns the collection of ModelBs related to that ModelA assuming you've fetched the related models and the collection has ModelBs in it.
The nice thing about Backbone-Relational is that it makes it easy to establish these defined relations automatically, on instantiation of the parent model. It also creates the reverse relation so traversing up and down from parent to child, child to parent is easy.
If I were manipulating ModelB and wanted to get to ModelA, I use the reverseRelation key I established parentA
.
someModelB.get('parentA'); // Points to the related ModelA
It also helps with bindings and some other problems that prop up when you have models in models in models. Relational works well with one to one, one to many and inverse relationships. There is a workaround with many to many but I don't think it's common because it's a difficult proposition with the way things are set up.
As for views, I'm not sure exactly what you're thinking but do you need to have a "collection" of views?
Let's say you have ModelA with a collection of ModelBs. Each ModelB has an associated view. This is illustrated very nicely with the concept of the old-fashioned LIST.
<div id="ModelAView">
<ul>
<li>ModelB_1</li>
<li>ModelB_3</li>
<li>ModelB_7</li>
</ul>
</div>
While there are a bunch of ModelBs, you already have them nice and tidy in a collection. If you go with a data driven way of managing your views, there is no need to put the view objects in another list. Instead, you can make them self managing!
// Assume when you instantiate ViewB, you pass to it a ModelB.
ViewB = Backbone.View.extend({
initialize: function() {
this.model.bind('remove', this.remove, this);
this.model.bind('update:colorAttr', this.updateColor, this);
},
updateColor: function() {
this.$el.css('color', this.model.colorAttr);
}
});
Now say you get rid of ModelB from your collection.
myModelA.get('modelBs').remove(someModelB);
Then the view associated with this modelB will automatically be removed from the view.
Not sure if this is what you had in mind. I usually go with this approach. Anyway, if there are more specifics just post em in the comments. Hope this helps.