5
votes

The question: The documentation is scarce, and I'm something of a noob -- can anyone confirm the proper (assuming there is one) way to bind Backbone.Views to instances of Backbone.RelationalModel (from backbone-relational.js) for updating/rendering to the dom? I've tried a handful of different approaches, based on the normal Model/View binding in Backbone, with little success.

The backstory (/more info): I'm learning the ropes with Backbone.js, and have had to pick up a lot over the past week. If I'm missing something obvious (which is highly likely -- including the "right" way to handle my problem below), please call me out.

I'm dealing with a mongodb-backed REST interface (that I don't have full control over -- or I would be re-architecting behavior on the server-side) that takes heavy advantage of nested dictionaries, so I've been reading up on how to best represent that in Backbone (while not breaking the great save() + server sync stuff that Backbone provides).

I've seen two options: backbone-relational and ligament.js.

I've started with backbone-relational.js, and have RelationalModels (backbone-relational's replacement for Backbone's standard Model) created for the various dictionaries in the tree that gets handed back by REST interface. The relationships between them are defined, and console logging the JSON from each model (in their respective initialize functions) shows that they're all being called/loaded up correctly off the server on a fetch() command at the overall collection level.

So, that's all great.

Problem: I've got views "listening" for updates on each of those models (and bound functions that should render templates on the dom), and they never "fire" at all (let alone render...). The main view fires on fetch(), no problem, loading the "top level" model and rendering it on the dom -- but the views that represent the "foreign key" models within that "top level" model never do (even though the data is DEFINITELY getting loaded into each model, as evidenced by the console logging on each model mentioned above).

Any insights would be greatly, greatly appreciated.

In direct response to Raynos reply below (thanks Raynos!): If I defined a base url for the UpperLevelCollection with the UpperLevelModels existing at (UpperLevelCollection url)/(UpperLevelModel id) on the server, how would I map those LowerLevelCollections to dictionary keys within the one JSON dump for each UpperLevelModel from the server-side? In other words, could using collections within models properly handle a data dump from the server like this (obviously very simplified, but gets at the issue) AND properly save/update/sync it back?

[{
    "some_key": "Some string",
    "labels": ["A","List","Of","Strings"],
    "content": [{
        "id": "12345"
        "another_key": "Some string", 
        "list": ["A","list","of","strings"],
    },{
        "id": "67890"
        "another_key": "Some string", 
        "list": ["A","list","of","strings"],
    }],
}]
2

2 Answers

2
votes

Generally for nested dictionaries I take the following approach

var UpperLevelCollection = Backbone.Collection.extend({
    model: UpperLevelModel
  }),
  UpperLevelModel = Backbone.model.extend({
    initialize: function() {
      this.nested = new LowerLevelCollection;
    }
  }),
  LowerLevelCollection = Backbone.Collection.extend({
    model: LowerLevelModel
  }),
  LowerLevelModel = Backbone.Model.extend({});

Just nest those collections inside models all the way down.

1
votes

The problem might be that as you load new data into you ParentModel, your child collection AFAIK is not actually fetched, it's wiped and replaced by a new collection (see Backbone.HasMany.OnChange on line 584 in backbone-relational.js). Thus your own bindings on the child collection are gone.

This is, in my opinion, a weakness with backbone-relational. This behavior should be configurable, with an option where a slower find-and-update-approach is used instead of wipe-and-replace.