2011-07-28 73 views
39

我已经获得了一大堆启动时加载的任务。
我想根据选定的列表/收件箱显示它们,以便每个列表不会有额外的负载。Backbone.js - 在视图中过滤和显示收集数据的正确方法

window.Task = Backbone.Model.extend({}); 

window.TasksCollection = Backbone.Collection.extend({ 
    model: Task, 
    url: '/api/tasks', 
    inbox: function() { 
     return this.filter(function(task) { 
      return task.get('list') == null; 
     }); 
    }, 
    list: function(id) { 
     return this.filter(function(task) { 
      return task.get('list') == id; 
     }); 
    } 
}); 

window.tasks = new TasksCollection; 

window.TaskView = Backbone.View.extend({ 
    tagName: 'li', 
    template: _.template($('#item-template').html()), 
    initialize: function() { 
     _.bindAll(this, 'render', 'close'); 
     this.model.bind('change', this.render); 
     this.model.view = this; 
    }, 
    render: function() { 
     $(this.el).html(this.template(this.model.toJSON())); 
     this.setContent(); 
     return this; 
    }, 
}); 

window.TasksView = Backbone.View.extend({ 
    el: '#todo-list', 
    collection: tasks, 
    initialize: function() { 
     _.bindAll(this, 'render'); 
     this.collection.bind('reset', this.render); 
     this.collection.fetch(); 
    }, 
    render: function() { 
     var t = this; 
     $(t.el).html(''); 
     this.collection.each(function(task) { 
      var view = new TaskView({ model:task }); 
      $(t.el).append(view.render().el); 
     }); 
     return this; 
    }, 
}); 

window.Nicetask = Backbone.Router.extend({ 
    routes: { 
     '':    'inbox', 
     '/inbox':  'inbox', 
     '/list/:id': 'list', 
    }, 
    initialize: function() { 
     _.bindAll(this, 'inbox', 'list'); 
     window.tasksView = new TasksView; 
    }, 
    inbox: function() { 
     tasks.reset(tasks.inbox()); 
    }, 
    list: function(id) { 
     tasks.reset(tasks.list(id)); 
    } 
}); 

此代码的工作,但reset()函数从任务收集实际列表中删除其它任务。而在另一条路线上,任务收集是空的。

是否有任何合理的方法来实现这一目标?谢谢你的任何想法。

PS:新手骨干


UPDATE

THX到@sled和@ibjhb征求意见,这里是工作液的片段。

window.TasksView = Backbone.View.extend({ 
    el: '#todo-list', 
    collection: Backbone.Collection.extend(), 
    initialize: function() { 
     _.bindAll(this, 'render', 'addOne', 'addAll'); 
     this.collection.bind('add', this.addOne); 
     this.collection.bind('reset', this.render); 
    }, 
    render: function(data) { 
     $(this.el).html(''); 
     _.each(data, function(task) { 
      this.addOne(task); 
     }, this); 
     return this; 
    }, 
    addOne: function(task) { 
     var view = new TaskView({ model:task }); 
     $(this.el).append(view.render().el); 
    }, 
}); 

window.Nicetask = Backbone.Router.extend({ 
    routes: { 
     '':    'inbox', 
     '/inbox':  'inbox', 
     '/today':  'today', 
     '/list/:id': 'list', 
    }, 
    initialize: function() { 
     _.bindAll(this, 'inbox', 'today'); 
     window.tasksView = new TasksView; 
     window.menuView = new MenuListView; 
     tasks.fetch(); 
    }, 
    inbox: function() { 
     tasksView.render(tasks.inbox()); 
    }, 
    today: function() { 
     tasksView.render(tasks.today()); 
    }, 
    list: function(id) { 
     tasksView.render(tasks.list(id)); 
    } 
}); 
+2

拉出我的头发一个小时。感谢你的回答! – Chev

+1

使用Backbone Marionette可能吗?这解决了很多问题。 – Blacksonic

+0

嗨Juraj,我有一个情况,我得到一个JSON树,我必须创建集合,只有当我们点击子节点。例如。 Root1> child1> subchild1。在这里,我必须首先显示根节点,并且只有在单击根节点'Root1'时应该显示子列表'child1'或者应该创建子集合。我刚刚发现你的情况有点类似。你能对此有所了解吗?在此先感谢 –

回答

4

我想你需要使用另一个集合。例如,在您的收件箱中,执行此操作:

inbox: function(){ 
    currentCollection = new TasksCollection(tasks.inbox()); 
} 

我还没有测试过这个,但是当您执行.reset();要删除所有模型和加载在通过的人。

1

一个快速修正你的解决方案,您使用的

$(this.el).html(''); 

我的理解是你的意见和相关事件绑定仍然会在浏览器中存在内存,因此理想情况下需要在TaskView上使用view.remove()来正确清除事件绑定以及html。


这是一个稍微不同的看法上,我一直在寻找一个解决类似的问题的答案,希望这可能是帮助他人。

我的问题: - 过滤模型属性的完整集合。例如。用户单击模型视图,获取(某些)属性列表,选择属性过滤集合以仅显示具有相同值的属性。

我走的路线是通过调用视图中的采集方法,在我的情况的看法是特定的模型,因此:

this.model.collection.myFilter(attr,val); 

其中attr是与相关的模型的属性收集,然后在过滤器类似

myFilter: function(attr, val){ 
    var groupByAttr = this.groupBy(function(article){ 
     var res = (val === undefined)? true : (article.get(attr) == val); 
     article.set({selected:res}); 
     return res; 
    }); 
    return groupByAttr; 
} 

我已经使用._groupBy因为这将返回2门阵列(正/负),其可以使用的。通过设置模式属性“选中”,并绑定到模型视图中,我可以很容易地切换显示或隐藏视图的类。

if(val === undefined)被添加为通过调用没有值的相同方法来清除过滤器的简单方法。

+0

有趣。你如何'JSONify'模板的结果? – charlysisto

4

@sled在您发布的代码中存在拼写错误,请参阅评论内嵌。你是否把这个作为项目发布在某个地方?

// add models 
add: function(models, options) { 
    // TYPO: next line was missing, so single models not handled. 
    models = _.isArray(models) ? models.slice() : [models]; 

    var self = this; 

    models = _.filter(models, this.filter); 

    // return if no models exist 
    // TYPO: returned undefined, so was not chainable 
    if(models.length == 0) { return this; } 

    // actually add the models to the superset 
    this.superset.add(models, options); 
    return this; 
}, 

// remove models 
remove: function(models, options) { 
    // TYPO: next line was missing, so single models not handled. 
    models = _.isArray(models) ? models.slice() : [models]; 

    // remove model from superset 
    this.superset.remove(_.filter(_.filter(models, function(cm) { 
    // TYPO: not 'm != null', causes error to be thrown 
    return cm != null; 
    }), this.filter), options); 
    // TYPO: missing return so not chainable 
    return this; 
}, 
相关问题