Backbone.Marionette is probably the best thing that ever happened to Backbone.
What is Backbone.js?
Backbone.js gives structure to web applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing API over a RESTful JSON interface.
What is Backbone.Marionette?
Backbone.Marionette is a composite application library for Backbone.js that aims to simplify the construction of large scale JavaScript applications. It is a collection of common design and implementation patterns found in the applications that I (Derick Bailey) have been building with Backbone, and includes various pieces inspired by composite application architectures, such as Microsoft’s “Prism” framework.
The need for filtered collections
Let’s say I have a collection A that can be updated dynamically both client-side and server-side (items added, removed, resorted). Let’s ViewA be a CollectionView
ListView = new Marionette.CollectionView({collection: A});
Elements of A have an attribute is_starred
. I’d like to provide a filter option in the UI that will cause ListView
to show only starred elements of A. I know the general pattern of filtering A on the is_starred
property to create a new collection AStarred
and pass it to ListView
. The problem is that when items are added or deleted to A, I also need them to be added/deleted to AStarred
if they’re starred.
What’s a good approach to achieve this?
One approach is to create a custom collection StarredCollection
that is initialized using A and listens on add/remove/reset events on A, and only adds/removes items that are starred, and then pass an instance of StarredCollection to ViewA.
Another approach is to create a custom view, StarredView
, with wrappers around addItemView
/removeItemView
that only calls the corresponding methods in the CollectionView
if the item passes a test. This could even be generalized to FilteredCollectionView
where a filter is parameter, so one could filter on whatever.
I went with the second approach.
Here is how I did it.
First, patch Marionette’s CollectionView
(I could’ve created a SortedCollectionView
instead, but this was easier in my case).
Then, say I have CollectionView called ListView, and I want to create a filtered version of it:
Or, if I’m showing the ListView in a Layout’s regions, then I create StarredLayout:
But I also modified on the ListLayout.onRender to pass the filter to the list view before creating the ListView:
Warning: this breaks the handling of EmptyView which will be shown only when the original collection is empty, not when filtered collection is empty.
I hope others find this useful and suggest ways of improving it.
This works nicely for me, but I would love to see more code context. For instance, I am unclear on what you mean by this: “But I also modified on the ListLayout.onRender to pass the filter to the list view before creating the ListView:” The code provided seems to refer to a static collection? TitanFile.channelList.
Thanks.