How to filter backbone. Collection

Source: Internet
Author: User

First of all, I want to talk about the topic of this article, because I don't know what name it is. Rendering list is the most common operation in our application. In backbone applications, we usually use the list as a collcetion, and then specify a view to display this collection, which is very convenient. But what if you need to filter a set and only show the parts that meet the criteria in the collection?

Rendering a collection in the memory is undoubtedly very simple, because backbone provides some operation methods. However, after filtering a collection, you may encounter unexpected difficulties in rendering the filtered results. This article will look for simple code to solve this problem.

Basic Filter Operations

Backbone. Collection has some methods for filtering and searching. Most of them are inherited from underscore. JS, but some are not. However, no matter where they come from, most of these methods have one thing in common: returnModels Array.

For examplewhereMethod. When this method is called, a model array with the attribute value you specified is returned.

var testCollection = new Backbone.Collection([    {name: "joy", age: 21},    {name: "jack", age: 20},    {name: "pater", age: 32},    {name: "daivd", age: 22},    {name: "gina", age: 21}]);var results = testCollection.where({    age : 21});

resultsIt will be an array with all{age: 21}OfmodelInconsoleLet's take a look:

Filter by View Control

It is quite easy to display the Filter list. The only problem is that the filter operation does not return a collection, but a model array. This is often surprising. How to deal with this array? How to display a backbone. View? In addition, when you need to display that the view of the array after the filtering operation has pointed to an original backbone. Collection, this problem will become more difficult.

You may say that this is very easy. Let's take a look at the following operations:

var FilteredView = Backbone.View.extend({    events: {        "click #run": "runFilter"    },    runFilter: function(e){        e.preventDefault();        this.filter = {            // ... get the filter info from the DOM        };        this.render();    },    render: function(){        var html = [],            template = _.template($("tmpl-demo").html());        var filteredList = this.collection.where(this.filter);        _.each(filteredList, function(item){              html.push(template(item.toJSON());        });        this.$el.html(html);        return this;    }  });

It looks good to some extent. The code is short, easy to understand, and solves the problem.

However, the above Code is only applicable to some simple scenarios. If you are dealing with simple situations, there may be no mistakes. But there are latent defects. When you continue to use the filter operation, you will find that the above Code has not been further filtered.

How can this problem be solved? Let's go back to the origin. We can perform various filtering operations on Backbone. Collection, right? Therefore, we need to make the filter operation return not an array, but a backbone. Collection object. But how?

Anti-pattern of Self-Filtering

If you try to filter the original collection and then update the collection, you will eventually get into a bad situation, or even worse than filtering in the view.

However, let's take a look at how to implement the above method:

var testCollection = Backbone.Collection.extend({    customFilter: function(filters){        var results = this.where(filters);        this.reset(results);    }});var testCollection = new Backbone.Collection([    {name: "joy", age: 21},    {name: "jack", age: 20},    {name: "pater", age: 32},    {name: "daivd", age: 22},    {name: "gina", age: 21}]);// filter the collectiontestCollection.customFiler({    age : 21});

Once you use a custom method to filter collections, there are only two items in the collection that meet the conditions. This seems to be an ideal result. If you want to use a new filter, it will only further filter the last result because the previous collection has been updated, this is not the result we want most of the time.

Create a filtered collection

If you want to use backbone. collection to process filtered arrays, you must convert the array to backbone. collection. There will be two collections: the original collection and the filtered collection. When you have the filtered collection, you can use backbone. View for direct rendering.

var results = testCollection.where({    age: 21});var filteredCollection = new Backbone.Collection(results);

Yes, it's that simple. Happy, but it can still be more convenient.

Returns the same collection type.

You may want to return an instance of the same type from a custom backbone. collection.

var testCollection = Backbone.Collection.extend({    customFilter: function(filters){        var results = this.where(filters);        return new testCollection(results);    }});var filteredCollection = testCollection.customFilter({    age: 21});

Update filter operation

When the filter condition changes, you need to update the collection and re-render it. The best operation is to instantiate only one filtered collection, and render the correspondingfilterView.

var FilteredView = Backbone.View.extend({    initialize: function(){        this.listenTo(this.collection, "reset", this.render, this);    } });var filteredCollection = new Backbone.Collection();var filteredView = new FilteredView({    collection: filteredCollection});$("#run").click(function(e){    var filter = {        // ...  new filters    };    var results = myCollection.where(filter);    filteredCollection.reset(results);});

Addition

Add an underscore.

UnderscoreinvokeThe method is a very useful method. Let's look at it:

var demoCollection = Backbone.Collection.extend({    model: demoModel,    selected : function() {        return this.filter(function(itm) {            return itm.get(‘selected‘);        });    }});var selected = demoCollection.selected();

I have already explained howfilterThe returned array becomes the backbone. Collection instance, but it is obvious that the array is returned here.

The following is generally the case when batch operations are performed. For example, if batch deletion is performed, We need to delete the selected batch operations. We may need to access an API and pass the ID to it.

IfselectedThe returned backbone. Collection instance object can be directly used.pluckMethod:

VaR IDs = selected. Pluck ('id'); // returns the array of IDs.

IfselectedWhat about the model array? How can I obtain the ID array?

You may passeachLoop:

var ids = [];_.each(selected, function(itm){    ids.push(itm.get(‘id‘));});

If you want to return more than an array of IDS,eachThe method is actually very suitable. If you want to return an array, there is actually a simpler method.

If you have any, go to the backbone source codepluckMethod, you will find that this method actually calls underscoreinvokeSo easy:

ids = _.invoke(selected, ‘get‘, ‘id‘);

If you want to delete them in batches from the collection, you can also directly:

_.invoke(selected, ‘destroy‘);//http://underscorejs.org/#invoke_.invoke(list, methodName, *arguments)

Therefore, multiple parameters can be passed, but an array is returned.

In fact, let's look at the underscore source code,invokeThe_.map, So you can also usemapMethod.

 

How to filter backbone. Collection

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.