Use Backbone.Marionette CollectionViews on a subset of a Backbone collection
Backbone VirtualCollection allows you display a subset of a Backbone collection in a Backbone view that updates in real time. It works great with Marionette CollectionViews.
If you're thinking "why don't you just place the models you're interested in a new collection?" the answer is that the new collection won't update itself when new models are added to the original collection, so you're creating data inconsitency. That's why we need a VirtualCollection.
a) with npm
npm install backbone-virtual-collection
b) or manually add
dist/backbone.virtual-collection.js directly to your web app.
For example, let's say you have a task collection, and want to show a list of tasks that belong to a specific user.
We can instantiate a virtual collection that only contains tasks that belong to Rupert (who has user_id 13).
The constructor takes two parameters, the first is the parent collection, the second is a options object. The
filter option specifies a function that takes the model as argument. You can also just specify a hash of attributes to match.
var virtual_collection = tasks_collectionreturn taskget'user_id' == 13;;// or using a hash of attributes to matchvirtual_collection = tasks_collectionfilter:user_id: 13;var view =collection: virtual_collection;
The Marionette collection view will only display the tasks that belong to Rupert, and it will update automatically. In other words, when a task is created that belongs to Rupert it will appear, but not if it belongs to Bob.
Be default, the virtual collection will have the same sorting order as the parent collection. However, a comparator can be specified to change this. The comparator behaves like a Backbone comparator. In other words, you can specify a function or the name of an attribute to sort by.
var virtual_collection = tasks_collectionfilter: user_id: 13comparator: 'name';// tasks in the virtual_collection will be sorted by name
You can also change the sorting order on the fly.
virtual_collectioncomparator = 'created_at';virtual_collectionsort; // triggers sort event// virtual_collection is now sorted by date, but the parent collection has not changed
The virtual collection will keep listening to its parent collection until you call
You can pass a
destroy_with option when creating the virtual collection being that an event emitter. The virtual collection will stop listening to events when the
destroy_with event emitter emits a
var virtual_collection = collectionfilter: foo: 'bar'destroy_with: view;
+Note: Prior to Marionette 2.*, "destroy" was called "close". For compatibility with older versions of Marionette, the old helper
virtual_collection.closeWith and option
close_with are still availble, handling the
It's very common that you'd want to update the filter being used and have the collection view update itself.
updateFilter takes the same parameters as the original
filter option (a hash, or a function) and regenerates the virtual collection without losing your view bindings.
virtual_collectionupdateFilterthe_new: 'properties'are: 'lovely';// orvirtual_collectionupdateFilterreturn modelfoo === 'bar';;
VirtualCollection does not store, or duplicate any data. We've used other solutions in the past, and duplicating data is just plain bad news.
VirtualCollection maintains an internal index of models that pass the filter. That way, using the accessors and iterators (
each, etc) is fast. It doesn't have to go through the whole parent collection and re-evaluate all the filters.