I'm getting nuts with this thing. I really can't figure out what's the issue here.
I have a collection of models called projects, and each of this project has its own projectviewitem.
The task I'm trying to perform is just deleting all models belonging to the collection. The corresponding model views should also be removed along the way. Here is how I do it:
empty: function() {
for(i=0; i<this.length; i++) {
var model = this.at(i);
console.log("script remove: "+model.get('id'));
model.destroy();
};
I'm making sure I'm destroying the right models with the console.log output which is giving me each model开发者_如何学Python id.
In the project model I have this destroy function:
destroy: function() {
console.log(this);
console.log("model remove: "+this.get('id'));
return Backbone.Model.prototype.destroy.call(this);
},
Again I'm making sure I deal with the proper model. I also inspect the structure of the model to be sure the callback is right.
The projectviewitem is initialized within the model's initialize method:
initialize: function() {
this.view = new ProjectViewItem({model: this});
},
It is bound to the model:
initialize: function() {
this.model.bind('destroy', this.remove, this);
...
And its destroy method is:
remove: function() {
console.log("remove: "+this.model.get('id'));
return Backbone.Model.prototype.remove.call(this);
},
About the console.log output now.
Here is what I get when emptying the collection.
script remove: 344
d (model 344 object)
model remove: 344
//here I should get "remove: 340", but I don't. That means the projectviewitem's remove method isn't called, but why?
script remove: 343
d (model 343 object)
model remove: 343
remove: 343
remove: 343
//model 343 makes two callback calls?
As a result, all models are deleted but only one view is. I don't understand how model 344 loses the callback to its view and how model 343 gets two.. When I check out the objects (>> d), the callbacks are alright. 344 has its own, same for 343, and they seem to be pointing to their corresponding view.
Any clue?
Until I solve this issue I add (this.view.remove();) to the model.destroy method. It works but I would definitely like to know why the binding is not working properly.
There are a few things that could be causing your problems here, though it's hard to know for sure without more code:
You can't use an incrementing
for
loop to delete items (destroy()
will remove the item from the collection), because you're changing the length as you go. The classic way to fix this is to iterate backwards, rather than forwards:empty: function() { for(i=this.length-1; i>=0; i--) { var model = this.at(i); console.log("script remove: "+model.cid); model.destroy(); }; }
The
.destroy()
method on a model with an id won't trigger thedestroy
event unless there's a successful response from the server (relevant code). So you need to make sure your server is responding with a 200 response to the DELETE request.As noted in my comment, I'm not sure what you're trying to do by calling
Backbone.Model.prototype.destroy.call(this)
on a view. I suspect this is a typo, either in your post or in your code, but I'm not sure what it would accomplish.
I hope at least one of these issues is the source of your problem. I have a working jsFiddle with a slightly modified version of your code here: http://jsfiddle.net/e8Uct/3/ - it's only using models created on the fly, though, so it's not dealing with the server callback.
As an aside, I personally don't like the pattern of initializing the view with the model - I'd rather do it the other way around, and keep the model wholly independent of the UI. But that's really a matter of taste.
精彩评论