Thursday, November 3, 2011

Backbone.js Model Relationships: An Ugly First Try

‹prev | My Chain | next›

Up tonight, I begin exploring object relationships in Backbone.js. At this time, we are not including a recipe on this topic in Recipes with Backbone—primarily because it may be entirely solved by backbone-relational. Still, it seems like a rich area for exploration...

First up, I add a few people to my CouchDB store:

Since I am using CouchDB design documents to filter appointments, I now need to exclude those "Person" beasties from my views:


For the time being, I am going to add invitees to appointments manually. So I grab the list of all people in my data store:


And add some of the IDs to the list of invitees for an upcoming appointment:


Back in my Backbone app, I add a <div class="invitees"> to the edit appointment dialog. Then, in the view that displays the dialog, I add a check for invitees. If the appointment has people invited to it, then the invitees section of the dialog should show:
    var AppointmentEdit = new (Backbone.View.extend({
      // ...
      render: function () {
        // ...
        var invitees = this.model.get("invitees");
        if (invitees && invitees.length > 0) {
          $('.invitees').show();
        }
        else {
          $('.invitees').hide();
        }
      },
      // ...
    });
Now, when I click on the upcoming appointment with invitees, I see the invitees section:

To get that invitees section to expand, I add a click handler that loads a collection view:
      showInvitees: function() {
        var collection = new Collections.Invitees({invitees: this.model.get("invitees")})
        var view = new Invitees({collection: collection});
        view.render();
        $('.invitees').replaceWith(view.el);
      }
This is not great code, but I load in the invitees one-by-one when fetched:
    var Invitees = Backbone.Collection.extend({
      model: Models.Invitee,
      url: '/invitees',
      initialize: function(options) {
        options || (options = {});
        this.invitees = options.invitees;
      },
      fetch: function() {
        var models = _.map(this.invitees, function(id) {
          var invitee = new Model.Invitee({id:id});
          invitee.fetch({async: false});
          return invitee;
        });
        this.reset(models);
      }
    });
And it works:
To a point. The invitees are loaded and displayed, but I am almost certain that I have gotten the design wrong (async: false is usually not a good thing). No matter, I will pick back up tomorrow whipping this into some semblance of shape.

Day #194

No comments:

Post a Comment