Try out our recently released Firebug extension - Backbone Eye : Understand Backbone application behavior without debugging JavaScript!

API


Backbone.AssociatedModel allows for associations to be set-up between other Backbone Models and Collections. To achieve this, extend Backbone.AssociatedModel to specify an array of relations. Each association (relation) is defined by the following attributes.
relatedModel
(required)
  • v0.5.1+ A function(relation, attributes) - which returns a reference to a AssociatedModel type.
    • relation : the specific relation object in the array of relations.
    • attributes : hash of new values passed in via set.
    See the recipes for an example of where this may be useful.
  • A reference to a Backbone.AssociatedModel type.
  • A fully qualified string which can be resolved to an object type on the global scope. (or user defined scopes specified via Backbone.Associations.scopes list)
  • v0.5.1+ A special value - Backbone.Self - can also be set. This special value is useful in self-reference scenarios.

key (required)
A string which references an attribute name on relatedModel.

type (required)
  • Backbone.One for 1:1 Associations.
  • Backbone.Many for 1:M Associations.

collectionType
(optional)
Used to determine the type of collection used for a Backbone.Many relation.

Note If collectionType attribute is specified, relatedModel is ignored.

  • A reference to a Backbone.Collection type.
  • A fully qualified string which can be resolved to an object type on the global scope. (or user defined scopes specified via Backbone.Associations.scopes list)
  • 0.6.0+ A function which returns a reference to a Backbone.Collection.

map (optional)
Specify a transformation function to convert the value before it is assigned to the key on the relatedModel.

Note In v0.5.2+, the map API is augmented to pass in a type parameter. The type parameter contains the target model (or collection) type which the passed-in id (or ids) will be eventually transformed to. Additionally, the map function is now invoked with the specific model instance as context. (versus a global function in v0.5.1)

remoteKey (optional)

v0.5.5+

Specify remoteKey to serialize the key to a different key name in toJSON() calls. Useful in ROR nested-attributes like scenarios.
isTransient (optional)

v0.5.5+

Default value is false. If isTransient is set to true, then the attribute will not be serialized in toJSON() calls.
serialize (optional)

v0.6.0+

Use this attribute to set an array of attributes (singleton or subset) which will be serialized to the server end-point. Default behavior is to serialize all attributes.

Specify 1:1 associations


Use Backbone.One to specify a 1:1 relationship between two Backbone Models. The key specifies the attribute on the AssociatedModel which will hold the instance of relatedModel.

var Employee = Backbone.AssociatedModel.extend({
    relations: [
        {
            type: Backbone.One, //nature of the relationship
            key: 'manager', // attribute of Employee
            relatedModel: 'Employee' //AssociatedModel for attribute key
        }
    ],
    defaults: {
        age : 0,
        fname : "",
        lname : "",
        manager : null
    }
});
                

Specify 1:M associations


Use Backbone.Many to specify a 1:M relationship between two Backbone Models. Otherwise, identical to specifying 1:1 associations.
var Location = Backbone.AssociatedModel.extend({
  defaults: {
    add1 : "",
    add2 : null,
    zip : "",
    state : ""
  }
});

var Project = Backbone.AssociatedModel.extend({
  relations: [
      {
        type: Backbone.Many,//nature of the relation
        key: 'locations', //attribute of Project
        relatedModel:Location //AssociatedModel for attribute key
      }
  ],
  defaults: {
    name : "",
    number : 0,
    locations : []
  }
});
            
To specify 1:M associations, one can alternatively use the collectionType property. This can be useful to specify implementation of custom or built-in properties at the Collection level.
var Location = Backbone.AssociatedModel.extend({
  defaults: {
    add1 : "",
    add2 : null,
    zip : "",
    state : ""
  }
});

var Locations = Backbone.Collection.extend({
    comparator: function(c){
        return c.get('number');
    },

    model: Location
});

var Project = Backbone.AssociatedModel.extend({
  relations: [
      {
        type: Backbone.Many,//nature of the relation
        key: 'locations', //attribute of Project
        collectionType: Locations, //Collection to be used.
        relatedModel: Location //Optional
      }
  ],
  defaults: {
    name : "",
    number : 0,
    locations : []
  }
});
            

Specify Reverse Associations


These are automatically inferred by Backbone-associations. You can access reverse associations via a parents property on the AssociationModel or Backbone Collection. Note that the parents property is an array - as there could be multiple parents for a given AssociatedModel or Collection. The parents property simply stores the references of objects pointing to it and is agnostic of the type of the object.
Remember : The parents property can contain different type instances
dept1 = new Department({
    name:"R&D",
    number:"23"
});

var emp1 = new Employee({
    fname:"Tom",
    lname:"Hanks",
    age:41,
    sex:"M"
});

var emp2 = new Employee({
    fname:"Michelle",
    lname:"Pfiefer",
    age:42,
    sex:"F"
});

emp1.set({"works_for":dept1});
emp2.set({"works_for":dept1});

dept1.parents //[emp1, emp2]

myco = new Company({
   name:"Github Inc"
});

myco.set({research:dept1});

dept1.parents //[emp1, emp2, myco]
                    
Prevent memory leaks
Available in v0.5.1+
Memory leaks may be inadvertently caused and parents property may have wrong values if objects are set to undefined (or null) directly. Call the cleanup method before setting any object to undefined to prevent this from happening. The example below clarifies.
//Could cause mem leaks if you set emp2 = undefined
//emp2 = undefined;
//dept1.parents.length === 3 //Should have been 2

emp2.cleanup();
emp2 = undefined;
//dept1.parents.length === 2

Specify Transformations


Use a map function to transform values before assigning them to a model attribute. Could be typically used to transform (master) ids to a (master) AssociatedModel references.
var MasterType = Backbone.Model.extend({
    defaults:{
        id:"-1",
        type:"",
        validations:""
    }
});

store = new Backbone.Collection([
    {id:1, type:"phone", validations:"regex to validate phone #s here"},
    {id:2, type:'email', validations:"regex to validate email formats here"}
], {model:MasterType});


var Field = Backbone.AssociatedModel.extend({
    relations:[
        {
            type:Backbone.One,
            key:'type',
            relatedModel:MasterType,
            map:function (type) {
                //a local master store holding the master data reference
                return store.findWhere({type:type});
            }
        }
    ],

    defaults:{
        type:undefined,
        data:undefined,
        name:""
    }

});

var phone = new Field({name:'Residence Phone', type:'phone' });
var email = new Field({name:'Primary Email', type:'email'});

phone.get('type').get('validations') //regex to validate phone #s
email.get('type').get('validations'), //regex to validate email
Note : v0.5.2+
From v0.5.2+, the map function is passed the current (AssociatedModel) instance as a context and an additional type parameter which specifies the type of the model to transform the ids to. For a detailed example, refer to this recipe.

Get & set values from the object graph


Retrieve values from the object graph
Values can be retrieved by either specifying a fully qualified path or by explicitly traversing the object graph.
emp.get('works_for.controls[0].locations[0].zip') //94404

//or

emp.get('works_for').get('controls').at(0).get('locations').at(0).get('zip');
Set values in the object graph
Values can be set by either specifying a fully qualified path or by explicitly traversing the object graph to that property before setting the value.
emp.set('works_for.locations[0].zip', 94403);

//or

emp.get('works_for').get('locations').at(0).set('zip',94403);

Serialize and De-serialize object graphs


It would not very meaningful (or speedy) for web applications to transfer object graphs in their entirety across the network . Most applications would save and fetch parts of the object hierarchy incrementally. Many times, the primary keys of the nested object may be serialized rather than the actual instance itself. Backbone-associations leaves these decisions to the application. The base Backbone framework (and associations) provides hooks to easily achieve this. A representative scenario is implemented using these hooks in this gist and corresponding fiddle.

Eventing


Once the object hierarchy instance is set up, the next step is to tune-in to any kind of changes (update, add, remove, destroy, sort etc) which happen in this object hierarchy. Views - for example - would like to re-render to reflect the new model data. This is the topic of the eventing section of the documentation.