开发者

How do I convert a filtered collection to JSON with Backbone.js?

So I have a collection in Backbone for a list of events. This collection has a method on it which filters the list based on a list of categories passed to it.

var Events = Backbone.Collection.extend({
    model: Event,
    url: settings.events_url,
    filtered: function(checked) {
        return this.filter(function(e) {
            if ($.inArray(e.get('category').name, checked) >= 0) {
                return true;
            } else {
                return false;
            }
        });
    }
});

What I need to be able to do is convert this filtered collection to JSON, the same way you would do the collection as a whole.

var events = new Events();
events.toJSON();

However, because the filtered collection is no longer an actual collection, but rather a list of models, I don't have the .toJSON() method available to me. Is there a way to convert my filtered collection to a real collection? Or is there an easier way to convert it to JSON?

Th开发者_JS百科anks!


The constructor for a collection can take a list of models as an argument so:

var events = new Events();
var filteredEvents = new Events(events.filtered(true));
console.log(filteredEvents.toJSON());


Why not make use of the standard API?

var checked = ['foo', 'bar', 'baz'],
    filtered = eventsCollection
        .chain()
        .filter(function(model) {
            return _.include(checked, model.get('category').name);
        })
        .invoke('toJSON')
        .value();

On a separate note, Events.filterByCategoryName method name is more explicit. However, I tend not to implement too many 'convenient' methods in my design and embrace the standard API by using them directly.


You could also try something like:

    filtered: function(checked) {
        return _.map(this.filter(function(e) {
            return $.inArray(e.get('category').name, checked) >= 0
        }), function(model) {
            return model.toJSON();
        });
    }

Starting from the inside out:

  1. The call to this.filter will return the list of filtered results as you had it already.
  2. The _.map will perform an action on each entry of the array it is passed (it simply returns the result of model.toJSON()).


You can do like so :

var myFilteredCollection = new Events(); 

_.each(myFilteredData, function(eventModel){
    myFilteredCollection.add(eventModel); 
});

myFilteredCollection.toJSON(); 


The way I solved it is running a reduce function on the collection. The advantage of this is that you only do a 1 pass on the collection itself, remembering only the valid models, and returning the JSON of the model if they pass validation.

The other solutions offered to build a new collection which is performance wise - terrible.

    getValidItems: function () {
        //return only valid items as json
        return this.collection.reduce(function (validItems, row) {
            if (row.isValid()) {
                validItems.push(row.toJSON());
            }
            return validItems;
        }, []);
    },


    //somewhere where you save
    save: function() {
        var validItems = this.getValidItems();
        //do something with valid items
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜