Backbone model.destroy() invoking error callback function even when it works fine?
Solution 1
@David Tuite comment:
"Ok I figured it out. It seems that Backbone expects the JSON response to be a JSON serialization of the record that was destroyed. However, Rails controller generators only return head :ok by default. I changed my JSON response to be render json: @listing_save where @listing_save is the record I just destroyed and it registers a success."
FYI - when you're doing a destroy, you don't need to return the full json for the destroyed model. you can return an empty json hash and it will work just fine. the only time you need to return the json for the model is on a save / update.
Solution 2
I had this same problem. In my delete method on the server (java), I didn't return anything. Just status 200/OK (or 204/No content). And so the "parsererror" problem was caused by jquery trying to convert the empty response into JSON, which failed (since "json" is the default data type).
My solution was to use the "text" dataType instead, which can be set in the options:
model.destroy({ dataType: "text", success: function(model, response) {
console.log("success");
}});
Solution 3
Your response must have status code 204 as you won't return any content. Since backbone uses a REST interface you should return different http status codes depending on the task.
David Tuite
Founder and CEO of Developer Portal company roadie.io
Updated on June 19, 2022Comments
-
David Tuite almost 2 years
I have a Backbone.js model that I'm trying to destroy when the user clicks a link in the model's view. The view is something like this (pseudocode because it's implemented in CoffeeScript which can be found at the bottom of the question).
var window.ListingSaveView = Backbone.View.extend({ events: { 'click a.delete': 'onDestroy' }, onDestroy: function(event){ event.preventDefault(); this.model.destroy({ success: function(model, response){ console.log "Success"; }, error: function(model, response){ console.log "Error"; } }); } });
When I click the
delete
link in the browser, I always getError
logged to the console even though my server records successful destruction of the associated database record and returns a 200 response. When I refresh the page (causing the collection to re-render from the DB) the model I deleted will be gone.One interesting this is that when I log the
response
in the error callback, it has statuscode200
indicating success but it also reportsstatusText: "parseerror"
whatever that means. There is no error in my server logs.What am I doing wrong?
This is the response from the server:
Object abort: function ( statusText ) { always: function () { complete: function () { done: function () { error: function () { fail: function () { getAllResponseHeaders: function () { getResponseHeader: function ( key ) { isRejected: function () { isResolved: function () { overrideMimeType: function ( type ) { pipe: function ( fnDone, fnFail ) { promise: function ( obj ) { readyState: 4 responseText: " " setRequestHeader: function ( name, value ) { status: 200 statusCode: function ( map ) { statusText: "parsererror" success: function () { then: function ( doneCallbacks, failCallbacks ) { __proto__: Object
Here is the server action that destroy interacts with (Ruby on Rails)
# DELETE /team/listing_saves/1.json def destroy @save = current_user.team.listing_saves.find(params[:id]) @save.destroy respond_to do |format| format.json { head :ok } end end
And here is the actual CoffeeScript implementation of the Backbone View for people who prefer it like that:
class MoveOutOrg.Views.ListingSaveView extends Backbone.View tagName: 'li' className: 'listing_save' template: JST['backbone/templates/listing_save'] events: 'click a.delete_saved': 'onDestroy' initialize: -> @model.bind 'change', this.render render: => renderedContent = @template(@model.toJSON()) $(@el).html(renderedContent) this onDestroy: (event) -> event.preventDefault() # stop the hash being added to the URL console.log "Listing Destroyed" @model.destroy success: (model, response)-> console.log "Success" console.log model console.log response error: (model, response) -> console.log "Error" console.log model # this is the ListingSave model console.log response
-
David Tuite over 12 yearsok ok you can have the points. Even if I did do half the work ;)
-
Mike Li over 12 yearsbackbone is so sensitive about the rails json result
-
Arvid Janson about 12 yearsWhile you don't have to return the model, it's quite nice to do that sometimes. One case when that actually is a nice approach is when you are not using the {wait: true} parameter of the destroy – that way, if the action fails, you can easily re-add the model to the collection, to keep the collection updated.
-
Drejc about 11 yearsReturning an empty "null" response also works (in combination with a 200 status code).
-
chikamichi almost 10 yearsNice catch. Thank you.
-
carpeliam over 9 yearsI've also used
model.destroy({contentType: false, processData: false})
.