To be quite honest I'm stuck trying to override Backbone's sync() method for a Model, I have the signature for the function in place, and it gets triggered correctly, but I don't know what to put in the function body in order for it to make a default call to DELETE but with extra arguments. ie.
class Master.Models.Member extends Backbone.Model urlRoot: '/api/members/' sync: (method, model, options) -> params = _.clone options Backbone.sync method, model, params
I call it like this:
...... remove: -> @model.destroy collective_id: the_id
My intention there, is to pass the collective_id param you see there to the server. But even though it's inside the options hash for sync() and I clone it, It won't make it to the server! How can I send that extra param to the server?
(As it is, the only thing that reaches the server is the Model's id)
Thanks in advance!
When you call .destroy(), .fetch() or .save() they all call Model.sync which only calls Backbone.sync. It's a proxy function. This is intended to provide a nice hook for modifying the AJAX behavior of a single model or any models that extend from that model.
JSON.stringify
and modify the contentType
when you've specified data to be sent with the delete request. model.destroy()
and optionally pass in an options
parameterstringify
and contentType
stuff. javacript version
var oldBackboneSync = Backbone.sync; Backbone.sync = function( method, model, options ) { // delete request WITH data if ( method === 'delete' && options.data ) { options.data = JSON.stringify(options.data); options.contentType = 'application/json'; } // else, business as usual. return oldBackboneSync.apply(this, [method, model, options]); }
Usage:
var model, SomeModel = Backbone.Model.extend({ /* urlRoot, initialize, etc... */}); model = new SomeModel(); model.destroy({ data: { /* data payload to send with delete request */ } });
override
// Create your own 'enhanced' model Backbone.EnhancedModel = Backbone.Model.extend({ destroy: function( options ) { if ( options.data ) { // properly formats data for back-end to parse options.data = JSON.stringify(options.data); } // transform all delete requests to application/json options.contentType = 'application/json'; Backbone.Model.prototype.destroy.call(this, options); } });
usage
var model, SomeModel = Backbone.EnhancedModel.extend({ /* urlRoot, initialize, etc... */}) model = new SomeModel(); SomeModel.destroy({ data: { /* additional data payload */ } });
If sending data with your destroy requests is an isolated thing, then this is an adequate solution.
When calling model.destroy()
pass in the data
and contentType
options like so:
javascript version/usage
var additionalData = { collective_id: 14 }; model.destroy({ data: JSON.stringify(additionalData), contentType: 'application/json' });
Backbone.js makes the assumption (view source) that delete requests do not have a data payload.
// delete methods are excluded from having their data processed and contentType altered. if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { params.contentType = 'application/json'; params.data = JSON.stringify(options.attrs || model.toJSON(options)); }
In their assumed RESTful API call, the only data required is the ID which should be appended to a urlRoot
property.
var BookModel = Backbone.Model.extend({ urlRoot: 'api/book' }); var book1 = new BookModel({ id: 1 }); book1.destroy()
The delete request would be sent like
DELETE => api/book/1 contentType: Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Params need to be sent in options.data
, so try:
coffeescript
remove: () -> @model.destroy data: JSON.stringify collective_id: the_id, contentType: 'application/json'
javascript
remove: function() { return this.model.destroy({ data: JSON.stringify({ collective_id: the_id }), contentType: 'application/json' }); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With