0

Using backbone.js:

I have a collection of ModelA that contains several attributes and also one "node" that holds several ModelB. ModelB also contains several attributes.

CollectionA

 ModelA
  Attribute 1
  .
  .
  Attribute n
  "Node"
     ModelB
       Attribute 1
       Attribute 2
     ModelB
       Attribute 1
       Attribute 2

 ModelA
  Attribute 1
  .
  .
  Attribute n
  "Node"
     ModelB
       Attribute 1
       Attribute 2
     ModelB
       Attribute 1
       Attribute 2

I'm still working on the views but the main idea is that the views should be structured in a similar way. (Collection View holds several View A that holds several View B). The same ModelB will never be shared between multiple ViewB.

Q1: Does the design make sense or is it any obvious flaws I should consider? (This is my first try with BackboneJs).

Q2: What is the best way to set up the "Node"? Right now I'm using an array of ModelBs. Is it possible to have a collection of ModelB on each ModelA instead? Which approach is better?

Any guidelines are appriciated!

I would also like to point out that I've read this excellent post on a related issue (recommended). That case did however not contain ModelB in a array/collection in the same way as this one does.

Community
  • 1
  • 1
Mattias Wolff
  • 897
  • 1
  • 6
  • 14
  • If it is your first try with Backbone, maybe you should take it easier and try building something simple first? That said I posted this some days ago: http://stackoverflow.com/questions/10871369/how-to-handle-relations-in-backbone-js/10873385#10873385 I am referring to the `getEventComments` there in particular. I am also not quite sure what you mean exactly with 'node', could you rewrite your pseudo code to some example Backbone code? – Mosselman Jun 05 '12 at 03:18

1 Answers1

2

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.

jmk2142
  • 8,581
  • 3
  • 31
  • 47