Reputation: 24985
I'm filtering a Backbone collection by running it through an _.each()
loop and removing items if they don't fit certain criteria.
For some reason, the loop always stops after filtering about half the collection.
I have two theories:
I've noticed that the loop always ends on the item positioned last in the collection. Maybe the items are passed to the loop in a random order, but the loop is referencing the "actual" order of the collection.
By removing items from the same collection being filtered, I'm messing up the loop and it thinks there are fewer items than there actually are.
Here's a working version: http://jsfiddle.net/aZ9zJ/. Can someone tell me what's going on?
--
By the way, I know about filtering functions like _.filter()
and _.where()
but prefer to avoid them because they return an array rather than a collection.
I'm open to switching over to a filtering function instead, but would still like to understand why the each/remove technique I'm trying doesn't work.
App.View.Items = Backbone.View.extend({
tagName: 'p',
initialize: function() {
Backbone.on('filter:now', this.filterItems, this);
this.filtered = new Backbone.Collection;
this.collection.each(function(item) {
this.filtered.add(item);
}, this);
this.filters = new Backbone.Collection([
{
property: 'director',
criteria: 'Orson Welles'
}
]);
Backbone.trigger('filter:now');
},
filterItems: function() {
this.filters.each(function(filter) {
this.filtered.each(function(item) {
if ( item.get(filter.get('property')) === filter.get('criteria') ) {
this.filtered.remove(item);
}
}, this);
}, this);
console.log(this.filtered);
}
});
Unfiltered collection:
var itemCollection = new App.Collection.Items([
{
title: 'Citizen Kane',
director: 'Orson Welles'
},
{
title: 'Touch of Evil',
director: 'Orson Welles'
},
{
title: 'The Third Man',
director: 'Orson Welles'
},
{
title: 'Jaws',
director: 'Steven Spielberg'
},
{
title: 'Magnificent Ambersons',
director: 'Orson Welles'
}
]);
Instantiate view:
var itemsView = new App.View.Items({ collection: itemCollection });
Upvotes: 0
Views: 126
Reputation: 36965
By the way, I know about filtering functions like _.filter() and _.where() but prefer to avoid them because they return an array rather than a collection.
But you should use them none the less.
Messing with the collection being filtered changes its length, so the results may be unpredictable. You should filter
your collection and then set
the array returned from this operation on your other collection.
this.filtered.set( this.collection.filter(function(item) {
return item.get(filter.get('property')) === filter.get('criteria');
}
))
Upvotes: 1