Computed properties in Backbone

bloudermilk picture bloudermilk · Mar 10, 2012 · Viewed 9.7k times · Source

I have a scenario where the data being manipulated on the client is presented and interacted with in a different way than it is represented on the server.

Consider the following event resource returned from the server.

{
  "id": 123,
  "start_at": 1331336004906,
  "end_at": 1331337704906
}

And the following template for editing:

<form>
  <!-- Notice how date and time are separated in the interface -->
  <input type="text" name="start_date" value="{{start_date}}" />
  <input type="text" name="start_time" value="{{start_time}}" />

  <!-- Instead of asking for an end date/time, we ask for the duration -->
  <input type="text" name="duration" value="{{duration}}" />

  <input type="submit" />
</form>

How would I go about treating start_date, start_time, and duration as attributes in my Backbone model without sending them to the server? Am I supposed to modify .toJSON()?

Answer

bes picture bes · Oct 31, 2012

I am using a combination of the initialize() function together with change event listeners to update derived attributes. The idea is first to compute the attributes on model initialization, and second to let the model listen to its own changes and update the attributes accordingly.

My solution looks roughly like this:

MyModel: Backbone.Model.extend({
    initialize: function() {
        this.updateDerivedAttributes();
        this.on('change:start_at', this.updateDerivedAttributes, this);
    },
    updateDerivedAttributes: function() {
        this.set({
            start_date: Utils.dateFromDate( this.get( "start_at" ) ),
            start_time: Utils.timeFromDate( this.get( "start_at" ) ),
            duration: Utils.youGetTheIdea()
        }, {silent:true});
    }
});