2013-01-16 60 views
1

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

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

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

什么是最好的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; 
    } 
}); 

回答

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; 
     } 
    } 
});