Backbone.js model.destroy() not sending DELETE request
Do your models have an ID? If not, the HTTP request won't be sent. – nikoshr May 14 at 18:03
Thanks so much! Nikoshr's little comment was exactly what I needed. I spent the last 5 hours messing with this. I just had to add an id to the defaults in my model.
oz.
Updated on June 07, 2022Comments
-
oz. almost 2 years
I've been trying for days to get this working and I just cannot figure out why when I have my view to destroy a model which belongs to a collection (which properly has a url attribute for the beginning fetch of models' data), only fires the destroy 'event' which is bubbled up to the collection for easy binding by my list view. But it does not ever send an actual DELETE request or any request to the server at all. Everywhere I look, I see everyone using either the collection's url attr, or urlRoot if the model is not connected to a collection. I've even tested before the actual this.model.destroy() to check the model < console.log(this.model.url());
I have not overwritten the destroy nor sync methods for backbone. Also each model does have an id attribute which is populated via the collection's fetch (from database records).
The destroy takes place in the list item view, and the collection's "destroy" event is bound in the list view. All that works well (the event handling), but the problem, again, is there's no request to the server.
I was hoping that backbone.js would do it automatically. That was what the documentation implies, as well as the numerous examples everywhere.
Much thanks to anyone who can give some useful input.
FYI: I'm developing on wampserver PHP 5.3.4.
ListItemView = BaseView.extend({ tagName: "li", className: "shipment", initialize: function (options) { _.bindAll(this); this.template = listItemTemplate; this.templateEmpty = listItemTemplateEmpty; }, events: { 'click .itemTag' : 'toggleData', 'click select option' : 'chkShipper', 'click .update' : 'update', 'click button.delete' : 'removeItem' }, // .... removeItem: function() { debug.log('remove model'); var id = this.model.id; debug.log(this.model.url()); var options = { success: function(model, response) { debug.log('remove success'); //debug.log(model); debug.log(response); // this.unbind(); // this.remove(); }, error: function(model, response) { debug.log('remove error'); debug.log(response); } }; this.model.destroy(options); //model.trigger('destroy', this.model, this.model.collection, options); } }); Collection = Backbone.Collection.extend({ model: Model, url: '?dispatch=get&src=shipments', url_put : '?dispatch=set&src=shipments', name: 'Shipments', initialize: function () { _.bindAll(this); this.deferred = new $.Deferred(); /* this.fetch({ success: this.fetchSuccess, error: this.fetchError }); */ }, fetchSuccess: function (collection, response) { collection.deferred.resolve(); debug.log(response); }, fetchError: function (collection, response) { collection.deferred.reject(); debug.log(response); throw new Error(this.name + " fetch failed"); }, save: function() { var that = this; var proxy = _.extend( new Backbone.Model(), { url: this.url_put, toJSON: function() { return that.toJSON(); } }); var newJSON = proxy.toJSON() proxy.save( newJSON, { success: that.saveSuccess, error: that.saveError } ); }, saveSuccess: function(model, response) { debug.log('Save successful'); }, saveError: function(model, response) { var responseText = response.responseText; throw new Error(this.name + " save failed"); }, updateModels: function(newData) { //this.reset(newData); } }); ListView = BaseView.extend({ tagName: "ul", className: "shipments adminList", _viewPointers: {}, initialize: function() { _.bindAll(this); var that = this; this.collection; this.collection = new collections.ShipmentModel(); this.collection.bind("add", this.addOne); this.collection.fetch({ success: this.collection.fetchSuccess, error: this.collection.fetchError }); this.collection.bind("change", this.save); this.collection.bind("add", this.addOne); //this.collection.bind("remove", this.removeModel); this.collection.bind("destroy", this.removeModel); this.collection.bind("reset", this.render); this.collection.deferred.done(function() { //that.render(); that.options.container.removeClass('hide'); }); debug.log('view pointers'); // debug.log(this._viewPointers['c31']); // debug.log(this._viewPointers[0]); }, events: { }, save: function() { debug.log('shipments changed'); //this.collection.save(); var that = this; var proxy = _.extend( new Backbone.Model(), { url: that.collection.url_put, toJSON: function() { return that.collection.toJSON(); } }); var newJSON = proxy.toJSON() proxy.save( newJSON, { success: that.saveSuccess, error: that.saveError } ); }, saveSuccess: function(model, response) { debug.log('Save successful'); }, saveError: function(model, response) { var responseText = response.responseText; throw new Error(this.name + " save failed"); }, addOne: function(model) { debug.log('added one'); this.renderItem(model); /* var view = new SB.Views.TicketSummary({ model: model }); this._viewPointers[model.cid] = view; */ }, removeModel: function(model, response) { // debug.log(model); // debug.log('shipment removed from collection'); // remove from server debug.info('Removing view for ' + model.cid); debug.info(this._viewPointers[model.cid]); // this._viewPointers[model.cid].unbind(); // this._viewPointers[model.cid].remove(); debug.info('item removed'); //this.render(); }, add: function() { var nullModel = new this.collection.model({ "poNum" : null, "shipper" : null, "proNum" : null, "link" : null }); // var tmpl = emptyItemTmpl; // debug.log(tmpl); // this.$el.prepend(tmpl); this.collection.unshift(nullModel); this.renderInputItem(nullModel); }, render: function () { this.$el.html(''); debug.log('list view render'); var i, len = this.collection.length; for (i=0; i < len; i++) { this.renderItem(this.collection.models[i]); }; $(this.container).find(this.className).remove(); this.$el.prependTo(this.options.container); return this; }, renderItem: function (model) { var item = new listItemView({ "model": model }); // item.bind('removeItem', this.removeModel); // this._viewPointers[model.cid] = item; this._viewPointers[model.cid] = item; debug.log(this._viewPointers[model.cid]); item.render().$el.appendTo(this.$el); }, renderInputItem: function(model) { var item = new listItemView({ "model": model }); item.renderEmpty().$el.prependTo(this.$el); } });
P.S... Again, there is code that is referenced from elsewhere. But please note: the collection does have a url attribute set. And it does work for the initial fetch as well as when there's a change event fired for saving changes made to the models. But the destroy event in the list-item view, while it does trigger the "destroy" event successfully, it doesn't send the 'DELETE' HTTP request.
-
GijsjanB over 10 yearsBe wary, adding an id attribute to defaults will break Backbone.Model.isNew() and subsequently .save()'s POST and PUT.
-
Bogdan Le almost 10 yearsI think oz. is a newbie in Stackoverflow and he doesnt know how todo that.