Is there a way to exclude certain property from my model when I sync?
For example, I keep in my model information about some view state. Let\'s say I have a picker m
I found some problems with the accepted solution, as options.data modifies the way Backbone makes the calls. Better using options.attrs as this:
Backbone.Model.extend({
save: function (attrs, options) {
options = options || {};
attrs = _.extend({}, _.clone(this.attributes), attrs);
// Filter the data to send to the server
delete attrs.selected;
options.attrs = attrs;
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
}
});
Having this same issue, I decided to create a small module that can help : https://github.com/lupugabriel1/backbone-model-save
This is how you can use it in your models:
var myModel = new Backbone.ModelSave.extend({
notSync: ['name', 'age']
});
my solution combine all the above. just use white list instead of black one .. this is good rule in general
define
attrWhiteList:['id','biography','status'],
and then overwrite the save
save: function(attrs, options) {
options || (options = {});
//here is whitelist or all
if (this.attrWhiteList != null )
// Filter the data to send to the server
whitelisted = _.pick(this.attributes, this.attrWhiteList);
else
whitelisted =this.attributes;
/* it seems that if you override save you lose some headers and the ajax call changes*/
// get data
options.data = JSON.stringify(whitelisted);
if ((this.get('id') == 0) || (this.get('id') == null))
options.type = "POST"
else
options.type = "PUT";
options.contentType = "application/json";
// options.headers = {
// 'Accept': 'application/json',
// 'Content-Type': 'application/json'
// },
// Proxy the call to the original save function
return Backbone.Model.prototype.save.call(this, attrs, options);
},
Based on several of the answers, this accounts for cases of null objects and a conditional in Backbone that doesn't sent the contentType
if options.data
is already set:
EDITABLE_ATTRIBUTES = ["name", "birthdate", "favoriteFood"];
...
save: function(attrs, options) {
// `options` is an optional argument but is always needed here
options || (options = {});
var allAttrs = _.extend({}, this.attributes, attrs);
var allowedAttrs = _.pick(allAttrs, EDITABLE_ATTRIBUTES);
// If `options.data` is set, Backbone does not attempt to infer the content
// type and leaves it null. Set it explicitly as `application/json`.
options.contentType = "application/json";
options.data = JSON.stringify(allowedAttrs);
return Backbone.Model.prototype.save.call(
this, allowedAttrs, options);
},
Since save
uses toJSON
we override it:
toJSON: function(options) {
var attr = _.clone(this.attributes);
delete attr.selected;
return attr;
},
But it may not work if you're using toJSON and need selected
in views for example. Otherwise you probably need to override save
method.
In Underscore 1.3.3 they added pick and in 1.4.0 they added omit which can be used very simply to override your model's toJSON
function to whitelist attributes with _.pick
or blacklist attributes with _.omit
.
And since toJSON
is used by the sync command for passing the data to the server I think this is a good solution as long as you do not want these fields wherever else you use toJSON
.
Backbone.Model.extend({
blacklist: ['selected',],
toJSON: function(options) {
return _.omit(this.attributes, this.blacklist);
},
});