过滤后如何使用原始的Backbone集合?

时间:2013-08-31 02:59:31

标签: javascript backbone.js backbone-views backbone-collections

我对Backbone相对较新,虽然我知道如何使用它的一般想法,但我的学习速度很快,我可能错过了一些关键元素。

所以我有一个包含名为“type”的属性的集合,可以是文章,书籍,视频,类。我有视图渲染和一切,但我需要能够在点击链接时过滤集合。

我的问题是 - 我如何让它过滤掉收藏品,并且当我点击其他类型时仍能重新过滤原始收藏品?

这是我的代码的要点,我简化了它以便于阅读:

var TagsView = Backbone.View.extend({
    initialize: function(query) {
        this.collection = new TagsCollection([], {query: self.apiQuery} );
        this.collection.on('sync', function() {
            self.render();
        });
        this.collection.on('reset', this.render, this);
    },
    render: function() {
        //renders the template just fine
    },
    filter: function() { 
        //filtered does work correctly the first time I click on it but not the second.
        var filtered = this.collection.where({'type':filter});
        this.collection.reset(filtered);
    }
});

更新:我设法让这个工作。我最终触发了一个过滤事件。

var TagsCollection = Backbone.Collection.extend({
    initialize: function(model, options) {
        this.query = options.query;
        this.fetch();
    },
    url: function() {
        return '/api/assets?tag=' + this.query;
    },
    filterBy: function(filter) {
        filtered = this.filter(function(asset) {
            return asset.get('type') == filter;
        });
        this.trigger('filter');
        return new TagsCollection(filtered, {query: this.query});
    },
    model: AssetModel
});

然后在我看来,我添加了一些东西来渲染我的新系列。

var TagsView = Backbone.View.extend({
    initialize: function(query) {
        this.collection = new TagsCollection([], {query: self.apiQuery} );
        this.collection.on('sync', function() {
            self.render();
        });
        this.collection.on('filter sync', this.filterTemplate, this);
        this.collection.on('reset', this.render, this);
    },
    render: function() {
        //renders the template just fine
    },
    filterCollection: function(target) {
        var filter = $(target).text().toLowerCase().slice(0,-1);
        if (filter != 'al') {
            var filtered = this.collection.filterBy(filter);
        } else {
            this.render();
        }

    },
    filterTemplate: function() {
        filterResults = new TagsCollection(filtered, {query: self.apiQuery});
        console.log(filterResults);
        $('.asset').remove();
        filterResults.each(function(asset,index) {
            dust.render('dust/academy-card', asset.toJSON(),     function(error,output) {
                self.$el.append(output);
            });
        });
    },  
});

3 个答案:

答案 0 :(得分:2)

它不能再次工作的原因是因为您在拨打reset时删除了与您的过滤器不匹配的模型。这是reset函数的正常行为。

不要使用视图的主集合进行渲染,而是尝试使用仅用于渲染的第二个集合来表示原始基本集合的过滤数据。所以你的观点看起来像是:

var TagsView = Backbone.View.extend({

    filter: null,

    events: {
        'click .filter-button': 'filter'
    },

    initialize: function (query) {
        this.baseCollection = new TagsCollection([], {query: self.apiQuery} );
        this.baseCollection.on('reset sync', this.filterCollection, this);
        this.collection = new Backbone.Collection;
        this.collection.on('reset', this.render, this);
    },

    render: function () {
        var self = this,
            data = this.collection.toJSON();

        // This renders all models in the one template
        dust.render('some-template', data, function (error, output) {
            self.$el.append(output);
        }); 
    },

    filter: function (e) { 
        // Grab filter from data attribute or however else you prefer
        this.filter = $(e.currentTarget).attr('data-filter');
        this.filterCollection();
    },

    filterCollection: function () { 
        var filtered;

        if (this.filter) {
            filtered = this.baseCollection.where({'type': this.filter});
        } else {
            filtered = this.baseCollection.models;
        }

        this.collection.reset(filtered);
    }

}); 

要删除所有过滤器,请设置一个类filter-button的按钮,使其具有空data-filter属性。然后将使用collection的所有模型重置baseCollection

答案 1 :(得分:1)

这是一个更好的答案。您可以使用where方法,而不是让它变得如此复杂。这是我对上述问题的替代解决方案。

filterby: function(type) {
      return type === 'all' ? this : new BaseCollection(this.where({type: type});
});

答案 2 :(得分:0)

您可以尝试使用Collection的比较器功能。

http://backbonejs.org/#Collection-comparator

基本上它就像整理你的收藏品一样。