GitXplorerGitXplorer
a

backbone-nested

public
444 stars
83 forks
44 issues

Commits

List of commits on branch master.
Unverified
7d69a1178056f99c69be4c381e4e3bdf016739ce

Merge pull request #159 from afeld/gh-pages

aafeld committed 7 years ago
Verified
1f6576a63e7613e84e19f0740c21a6f89f7c9f3f

move DocumentUp to be a development dependency in Bower

aafeld committed 7 years ago
Verified
18d5c1466e1dc086a1e175b89ef22e27074d609d

resolve test page dependencies

aafeld committed 7 years ago
Verified
1b470f93cfaed9c0d85995a5adc75c0ac24a5475

Merge remote-tracking branch 'origin/master' into gh-pages

aafeld committed 7 years ago
Unverified
6405946fedaace9bd2e369a019a17bbcf7c518ef

Merge pull request #158 from FortesSolutions/master

aafeld committed 7 years ago
Unverified
9577773da9fc487c89497db64ac81f5e1aafe7b3

Set package numbering back to original

committed 7 years ago

README

The README file for this repository.

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

Recommended.

  1. Install the latest version:

    bower install backbone backbone-nested-model jquery underscore --save
  2. Add backbone-nested.js to your HTML <head>:

    <!-- must loaded in this order -->
    <script type="text/javascript" src="/bower_components/jquery/jquery.js"></script>
    <script type="text/javascript" src="/bower_components/underscore/underscore.js"></script>
    <script type="text/javascript" src="/bower_components/backbone/backbone.js"></script>
    <script type="text/javascript" src="/bower_components/backbone-nested-model/backbone-nested.js"></script>

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.