Skip to content

503 Nested Model Attribute

zarlex edited this page Mar 6, 2017 · 1 revision

Nested model attribute

We extend our HeroModel with a nested collection attribute superPowers for the super powers a hero can have.

Hero Model

Open the file hero.model.js in the folder hero/models add add the nested property superPowers

return MwPortalModel.extend({
  ...
  nested: function () {
    return {
      superPowers: SuperPowersCollection
    };
  }
});

Nested

Nested has to be a function that has to return an object. The object can have multiple key value pairs. The value has to be either a Model (but not an instance) or a Collection. When the model is created it will create an instance of all nested values. Those instances are set as model attributes by their key In this example you would call get model.get('superPowers') to get the super powers instance.

Nested Collection

When you set a nested collection property the model try to resolve all set calls and backend responses that into the nested collection.

So when you call model.set('superPowers', [{id: 1}, {id: 2}]) it will take the array and put it into the nested collection. So instead of having an array of superPowers you have a BackboneJS collection.

Those cases are automatically resolved into the nested collection

  • model.set({superPowers: [{id: 1}]})
  • model.set({superPowers: [1,2,3]})
  • model.set('superPowers', [{id: 1}]})
  • model.set('superPowers', [1,2,3])

For the case that the items of the array are no objects it will use the model idAttribute of the nested collection model. So when the idAttribute of the nested collection model is xyz and the array contains primitive values it will create an object from each primitive value with the id attribute xyz as key.

[1,2,3] would become [{xyz: 1, xyz:2, xyz: 3}]

Nested Model

When you set a nested model property it is working similiar to the nested collection. Instead of array the nested model will resolve objects into models.

So when you have a sample model that looks like this:

return MwPortalModel.extend({
  ...
  nested: function () {
    return {
      superPower: SuperPowerModel
    };
  }
});

and you call model.set('superPower', {id: 1}) it will create a model instance from SuperPowerModel and set the model attributes.

Those cases are automatically resolved into the nested model

  • model.set({superPower {id: 1}})
  • model.set({superPower: 1})
  • model.set('superPower', {id: 1}})
  • model.set('superPower', 1)

Similar to the collection when the value is primitive it will use the idAttribute of the nested model to make an object.

So when the idAttribute of the nested model is xyz and the value is primitive it will create an object from the primitive value with the id attribute xyz as key.

1 would become {xyz: 1}

Receiving/Sending data with nested objects

You can use the parse method of the model to bring the backend response into the right shape. Make sure that the values for nested collection attributes are always an array.

When the model is saved all nested attributes are transformed into JSON objects. Before the result is sent to the server it is passed through the method compose(). This method is the counterpart of the parse() method. Here you can bring the JSON object into the right shape for the server. The result of compose() will be sent to the server.

When you have the nested attribute {superPowers: SuperPowersCollection} but the server only needs id's instead of objects you can do something like this:

return MwPortalModel.extend({
  ...
  nested: function () {
    return {
      superPowers: SuperPowersCollection
    };
  },
  compose: function(attrs){
    attrs.superPowers = _.pluck(attrs.superPowers, 'id');
    return attrs;
  }
});
Clone this wiki locally