Add Rails-like nested attributes support for Backbone.Model.
Add this line to your application's Gemfile:
gem 'backbone-nested-attributes'
And then execute:
$ bundle
Or install it yourself as:
$ gem install backbone-nested-attributes
Then, add this line in your application.js
:
//= require backbone-nested-attributes/all
Make your model extend from Backbone.NestedAttributesModel
, instead of Backbone.Model
and declare your relationships:
var Post = Backbone.NestedAttributesModel.extend({
relations: [
{
type: 'one',
key: 'author',
relatedModel: function () { return Person }
},
{
key: 'comments',
relatedModel: function () { return Comment }
}
]
})
var Comment = Backbone.NestedAttributesModel.extend({})
var Person = Backbone.NestedAttributesModel.extend({})
Now you can create your posts like this:
var post = new Post({
id: 123,
title: 'My Title',
author: { id: 987, name: "Vicente Mundim" },
comments: [
{
id: 765,
body: "Nice writeup!"
},
{
id: 766,
body: "Keep it going!"
}
]
})
post.get('author') // returns a Person model
post.get('comments') // returns a Backbone.Collection of Comment models
When saving data, you can choose whether to send attributes as usual, or with nested attributes support by giving { nested: true }
to save
:
post.save({}, { nested: true })
This will send data to the server like this:
{
id: 123,
title: 'My Title',
author_attributes: { id: 987, name: "Vicente Mundim" },
comments_attributes: [
{
id: 765,
body: "Nice writeup!"
},
{
id: 766,
body: "Keep it going!"
}
]
}
It keeps track of deleted models in 1-N
relations:
var comment = post.get('comments').at(0)
post.get('comments').remove(comment)
post.save({}, { nested: true })
Send this data to the server:
{
id: 123,
title: 'My Title',
author_attributes: { id: 987, name: "Vicente Mundim" },
comments_attributes: [
{
id: 765,
body: "Nice writeup!",
_destroy: true
},
{
id: 766,
body: "Keep it going!"
}
]
}
If you're using some bind plugin and you want to cancel changes that were made without reloading the page or hitting the backend you'll definitively want to take a look at Backbone.UndoableModel:
var Post = Backbone.UndoableModel.extend({
relations: [ // UndoableModel is a NestedAttributesModel, so it can have relations
{
type: 'one',
key: 'author',
relatedModel: function () { return Person }
},
{
key: 'comments',
relatedModel: function () { return Comment }
}
]
})
var Comment = Backbone.UndoableModel.extend({})
var Person = Backbone.UndoableModel.extend({})
var post = new Post({
id: 123,
title: 'My Title',
author: { id: 987, name: "Vicente Mundim" },
comments: [
{
id: 765,
body: "Nice writeup!"
},
{
id: 766,
body: "Keep it going!"
}
]
})
post.set({ title: 'My new title' })
post.get('author').set({ name: 'Jon Snow' })
post.get('comments').at(0).set({ body: 'Great post!' })
post.undo() // that's it, post is now reverted to its initial attributes, as well as its relations
post.get('title') // 'My Title'
post.get('author').get('name') // 'Vicente Mundim'
post.get('comments').at(0).get('body') // "Nice writeup!"
Check out the specs:
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request