骨干客户端收集过滤

时间:2013-01-16 19:14:59

标签: backbone.js

考虑一个骨干应用程序,它具有select类别列表,以及一个下面的文件表。所有文件,无论它们属于哪个类别,都在App.collection.files集合中。当用户选择新类别时,我想过滤表格以仅显示那些匹配的文件。

我想在客户端完全这样做。每次选择新类别时,我都不想从服务器获取新的文件列表。

我打算在App.collection.files.where({category_id: xx})App.View.Files.render()来完成过滤。

触发/响应事件以使其正常工作的最佳Backbone-y方式是什么?

我正在玩的一个想法是另一个包含过滤文件的集合,但不确定这是否是最好的方法。

App.View.FilesPage = Backbone.View.extend({
    template: App.utils.template('files-page'),
    className: 'container-fluid',
    initialize: function(){
        this.render();
    },
    render: function(){
        this.$el.html(this.template());

        this.$el.find('.categories').append(
            new App.View.Categories({collection:App.collection.categories}).el
        );

        this.$el.find('.files table').append(
            new App.View.Files({collection:App.collection.files}).el
        );

        return this;
    }
});

App.View.Categories = Backbone.View.extend({
    tagName: 'select',
    events: {
        'change': 'onChange'
    },
    initialize: function(){
        this.$el.attr('size', this.collection.length + 1);

        this.render();
    },
    render: function(){
        var option = function(value, text, isSelected){
            return $('<option></option>', {'value':value, 'text':text});
        };

        this.$el.html(option(0, 'All Documents'));

        this.$el.append(
            this.collection.invoke(function(){
                return option(this.get('category_id'), this.get('title'));
            })
        ).val(0);

        return this;
    },
    onChange: function(event){

    }
});

App.View.Files = Backbone.View.extend({
    tagName: 'tbody',
    initialize: function(){
        this.render();
    },
    render: function(){         
        this.$el.html(
            this.collection.invoke(function(){
                return new App.View.File({model:this}).el;
            })
        );

        return this;
    }
});

1 个答案:

答案 0 :(得分:0)

这是我提出的一个解决方案,表面看起来很精致和花哨。

在评论中调出代码更改。

对此解决方案的想法,以及完全不同的解决方案是受欢迎的。

App.View.FilesPage = Backbone.View.extend({
    template: App.utils.template('files-page'),
    className: 'container-fluid',
    initialize: function(){
        // CHANGE: Store application wide reference to 'Categories' model
        App.model.categories = new App.Model.Categories();

        this.render();
    },
    render: function(){
        this.$el.html(this.template());

        this.$el.find('.categories').append(
            new App.View.Categories({
                // CHANGE: Pass model into 'Categories' view
                model: App.model.categories,
                collection: App.collection.categories
            }).el
        );

        this.$el.find('.files table').append(
            new App.View.Files({collection:App.collection.files}).el
        );

        return this;
    }
});

App.View.Categories = Backbone.View.extend({
    tagName: 'select',
    events: {
        'change': 'onChange'
    },
    initialize: function(){         
        this.$el.attr('size', this.collection.length + 1);

        this.render();
    },
    render: function(){
        var option = function(value, text, isSelected){
            return $('<option></option>', {'value':value, 'text':text});
        };

        this.$el.html(option(0, 'All Documents'));

        this.$el.append(
            this.collection.invoke(function(){
                return option(this.get('category_id'), this.get('title'));
            })
        ).val(0);

        return this;
    },
    onChange: function(){
        // CHANGE: Update attribute within 'Categories' model
        this.model.set('category_id', this.$el.val());
    }
});

App.View.Files = Backbone.View.extend({
    tagName: 'tbody',
    initialize: function(){     
        this.collection.on('reset', this.render, this);
        // CHANGE: Listen for change on 'Categories' model, and re-render this view
        App.model.categories.on('change:category_id', this.render, this);

        this.render();
    },
    render: function(){
        this.$el.html(
            _.invoke(this.getFilteredFiles(), function(){
                return new App.View.File({model:this}).el;
            })
        );

        return this;
    },
    // CHANGE: Return a filtered set of models from collection, based on 'Categories' model attributes
    getFilteredFiles: function(){
        var categoryId = App.model.categories.get('category_id');

        if (categoryId!=0){
            return this.collection.where({'category_id': categoryId});
        }
        else{
            return this.collection.models;
        }
    }
});