Need help with backbone-nested?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

afeld
453 Stars 85 Forks MIT License 288 Commits 46 Opened issues

Description

A plugin to make Backbone.js keep track of nested attributes - looking for maintainers! https://github.com/afeld/backbone-nested/issues/157

Services available

!
?

Need anything else?

Contributors list

Backbone-Nested Build Status

A plugin to make Backbone.js keep track of nested attributes. Download the latest version and see the changelog/history/release notes on the Releases page. Supports Backbone 0.9.x and 1.x.

The Need

Suppose you have a Backbone Model with nested attributes, perhaps to remain consistent with your document-oriented database. Updating the nested attribute won't cause the model's

"change"
event to fire, which is confusing.
var user = new Backbone.Model({
  name: {
    first: 'Aidan',
    last: 'Feldman'
  }
});

user.bind('change', function(){ // this is never reached! });

user.get('name').first = 'Bob'; user.save();

Wouldn't it be awesome if you could do this?

user.bind('change:name.first', function(){ ... });

Installation

Bower

Recommended.

  1. Install the latest version:

    bower install backbone backbone-nested-model jquery underscore --save
    
  2. Add

    backbone-nested.js
    to your HTML
    :
    
    
    
    

Manual

Download the latest release and the dependencies listed above, then include with script tags in your HTML.

Usage

  1. Change your models to extend from

    Backbone.NestedModel
    , e.g.
    var Person = Backbone.Model.extend({ ... });
    
    

    // becomes

    var Person = Backbone.NestedModel.extend({ ... });

  2. Change your getters and setters to not access nested attributes directly, e.g.

    user.get('name').first = 'Bob';
    
    

    // becomes

    user.set({'name.first': 'Bob'});

Best of all,

Backbone.NestedModel
is designed to be a backwards-compatible, drop-in replacement of
Backbone.Model
, so the switch can be made painlessly.

Nested Attributes

get()
and
set()
will work as before, but nested attributes should be accessed using the Backbone-Nested string syntax:

1-1

// dot syntax
user.set({
  'name.first': 'Bob',
  'name.middle.initial': 'H'
});
user.get('name.first') // returns 'Bob'
user.get('name.middle.initial') // returns 'H'

// object syntax user.set({ 'name': { first: 'Barack', last: 'Obama' } });

1-N

// object syntax
user.set({
  'addresses': [
    {city: 'Brooklyn', state: 'NY'},
    {city: 'Oak Park', state: 'IL'}
  ]
});
user.get('addresses[0].state') // returns 'NY'

// square bracket syntax user.set({ 'addresses[1].state': 'MI' });

Events

"change"

"change"
events can be bound to nested attributes in the same way, and changing nested attributes will fire up the chain:
// all of these will fire when 'name.middle.initial' is set or changed
user.bind('change', function(model, newVal){ ... });
user.bind('change:name', function(model, newName){ ... });
user.bind('change:name.middle', function(model, newMiddleName){ ... });
user.bind('change:name.middle.initial', function(model, newInitial){ ... });

// all of these will fire when the first address is added or changed user.bind('change', function(model, newVal){ ... }); user.bind('change:addresses', function(model, addrs){ ... }); user.bind('change:addresses[0]', function(model, newAddr){ ... }); user.bind('change:addresses[0].city', function(model, newCity){ ... });

"add" and "remove"

Additionally, nested arrays fire

"add"
and
"remove"
events:
user.bind('add:addresses', function(model, newAddr){ ... });
user.bind('remove:addresses', function(model, oldAddr){ ... });

Special Methods

add()

Acts like

set()
, but appends the item to the nested array. For example:
user.get('addresses').length; //=> 2
user.add('addresses', {
  city: 'Seattle',
  state: 'WA'
});
user.get('addresses').length; //=> 3

remove()

Acts like

unset()
, but if the unset item is an element in a nested array, the array will be compacted. For example:
user.get('addresses').length; //=> 2
user.remove('addresses[0]');
user.get('addresses').length; //=> 1

See also

Note, this plugin does not handle non-embedded relations (a.k.a. relations), which keeps it relatively simple. If you support for more complex relationships between models, see the Backbone plugin wiki page. There is also an open discussion about merging this project with backbone-deep-model.

Contributing

Pull requests are more than welcome - please add tests, which can be run by opening test/index.html. They can also be run from the command-line (requires PhantomJS):

$ npm install
$ grunt

See also: live tests for latest release.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.