I've just started using backbone.js and I'm adding some basic methods to extend a collection allowing me to iterate through a collection and save all models, and iterate through a collection to destroy all models. I realise that bulk updates aren't RESTful, but I'm only updating to local storage so didn't think it would be an issue to do multiple updates.
In my base application, the collection has 9 models. When I call collection.saveModels() it correctly logs the length of the collection, and correctly saves all the models.
When I call collection.deleteModels() it correctly logs the length of the collection, but skips every second model (i.e. the 2nd, 4th, 6th, 8th). Each time delete is pressed it continues to only delete the odd indexed element, with the last item to be deleted being the 8th original item.
Is it possible I'm using the each function incorrectly, despite it working perfectly when I save?
_.extend(Backbone.Collection.prototype, Backbone.Events, {
saveModels : function() {
console.log(this.length);
this.each(function(model){
console.log('saving model ' + model.get('name'));
model.save();
});
},
deleteModels : function() {
console.log(this.length);
this.each(function(model){
console.log('deleting model ' + model.get('name'));
model.destroy();
});
}
});
and they are called like so: mycollection.saveModels();
and mycollection.deleteModels();
I realise I can iterate through the collection based on length, but I'd rather use the built in method where possible.
I've just started using backbone.js and I'm adding some basic methods to extend a collection allowing me to iterate through a collection and save all models, and iterate through a collection to destroy all models. I realise that bulk updates aren't RESTful, but I'm only updating to local storage so didn't think it would be an issue to do multiple updates.
In my base application, the collection has 9 models. When I call collection.saveModels() it correctly logs the length of the collection, and correctly saves all the models.
When I call collection.deleteModels() it correctly logs the length of the collection, but skips every second model (i.e. the 2nd, 4th, 6th, 8th). Each time delete is pressed it continues to only delete the odd indexed element, with the last item to be deleted being the 8th original item.
Is it possible I'm using the each function incorrectly, despite it working perfectly when I save?
_.extend(Backbone.Collection.prototype, Backbone.Events, {
saveModels : function() {
console.log(this.length);
this.each(function(model){
console.log('saving model ' + model.get('name'));
model.save();
});
},
deleteModels : function() {
console.log(this.length);
this.each(function(model){
console.log('deleting model ' + model.get('name'));
model.destroy();
});
}
});
and they are called like so: mycollection.saveModels();
and mycollection.deleteModels();
I realise I can iterate through the collection based on length, but I'd rather use the built in method where possible.
Share Improve this question edited Aug 7, 2015 at 11:54 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked Jun 20, 2011 at 6:51 djlumleydjlumley 2,9672 gold badges26 silver badges30 bronze badges 4- 3 the main problem, in general, with deleting things in loops is that it messes up where the loop currently is - the length of the loop gets shortened, and the "next" item index actually refers to the item after the next one - for example, if you delete the first item, the next index for the loop would be the second item, but what was the second item is now the first - so the third item is now the second - hope that makes sense – kinakuta Commented Jun 20, 2011 at 6:54
- Ah, that's it. Didn't even think about that! – djlumley Commented Jun 20, 2011 at 6:55
- 1 Seems you would need to loop using length, but loop backwards in any case – mplungjan Commented Jun 20, 2011 at 7:39
- @kinakuta you should write that as the answer. I believe it's correct – Pablo Fernandez Commented Jun 21, 2011 at 3:57
4 Answers
Reset to default 8The code bradgonesurfing posted doesn't actually work as the clone method doesn't return an underscore object. The correct way is to use the _.chain method with makes each method chainable.
_.chain(App.articles.models).clone().each(function(model){
console.log('deleting model ' + model.get('name'));
model.destroy();
});
The code below worked great for me:
destroyAll: function (options) {
while (this.models.length > 0) {
this.models[0].destroy(options);
}
}
Every time you call model.destroy() it removes itself from the collection. The each iterator doesn't know this. Do something like the following.
_.chain(App.articles.models).clone().each(function(model){
console.log('deleting model ' + model.get('name'));
model.destroy();
});
Backbone has access to underscore.js utils. First clone the models array then iterate over that and then destroy each model. Should work
This is the implementation of kinakuta's
ment I ended up using.
destroy_models : function() {
for (var i = this.length - 1; i > -1; i -=1){
this.getByCid('c'+i).destroy();
}
}