Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem of iteration on subcollection that modifies model triggering attributes #3

Open
alexstrat opened this issue Feb 4, 2013 · 2 comments

Comments

@alexstrat
Copy link

I've got a sub-collection that filters on an attribute value.

When I iterate on this sub-collection to modify attribute's value (the modification should remove the model from the collection), only half of the models are concerned by the modification.

coll = new Backbone.Collection();

for(var i=0; i<10; i++){
    coll.add(new Backbone.Model({
      id : 'model_'+i,
      selected: true
    }));
}

sub = coll.subcollection({
    filter: function(model) {
        return model.get('selected');
    },
    triggers: 'selected'
});


console.log('sub.length '+sub.length);
// sub.length 10

sub.each(function(model) {
    console.log('unselect '+model.get('id'));
    model.set('selected', false);
});
// unselect model_0
// unselect model_2 
// unselect model_4
// unselect model_6
// unselect model_8

console.log('sub.length '+sub.length);
// sub.length 5

I reproduced the bug in http://jsbin.com/elisor/3/edit.
I'm not sure it's a bug, since iterating on a collection that modifies itself is maybe not a feature, but I would like to know the workaround in this case.

However, Backbone handles well the case of removing of model while iterating on a collection. EDIT: backbone does not support that (http://jsbin.com/elisor/2/edit)

@alexstrat
Copy link
Author

For the moment I found this workaround: http://jsbin.com/elisor/4/edit

sub.clone().each(function(model) {
    console.log('unselect '+model.get('id'));
    model.set('selected', false);
});

@anthonyshort
Copy link
Owner

It's the each method that is the problem. Iterating over the collection and removing things mid-way will cause issues. In the past I've manually looped over the models in the collection or cloned it like you had there.

You could also silence those changes and call the refresh method on the subset so it will update.

sub.each(function(model) {
    console.log('unselect '+model.get('id'));
    model.set('selected', false, { silent: true });
}).filterer.refresh();

Not the prettiest but you'll always have issues with things like this with the each method. I'll have a think about it. Maybe there is a better solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants