我正在尝试在Ember.js中实现“分组依据”功能,并证明它比我原先想象的更难。
[{date: '2014-01-15T16:22:16-08:00', message: 'Tidal wave occurred'},
{date: '2014-01-15T05:00:16-08:00', message: 'Tornado destroyed town'},
{date: '2014-01-13T14:22:16-08:00', message: 'Volcanic eruption, likely'},
{date: '2014-01-13T16:24:16-08:00', message: 'Ice shelf calving off completely'},
{date: '2014-01-11T11:27:26-08:00', message: 'Mother-in-law visiting'}]
我正在寻找类似于此的最终输出:
Today
----------
4:22 pm - Tidal wave occurred
5:00 am - Tornado destroyed town
Monday
----------
2:22 pm - Volcanic eruption, likely
...etc., etc.
现在这个数据绑定到ArrayController。每个对象都有一个计算属性,以获得分组比较的“年/月/日”。
var ActivityController = Em.ArrayController.extend({
groupedResults: function () {
var result = [];
//Iterate over each item in the list, but do what with it?
this.get('content').filter(function (item) {
});
return result;
}.property('content.[]')
});
有关实施此方法的最佳方法的任何提示? Ember附带filterBy和mapBy,但没有groupBy。
答案 0 :(得分:6)
这是一个我已经改编的Groupable实现:
Groupable = Ember.Mixin.create
group: null
ungroupedContent: null
groupedContent: (->
model = @
groupedContent = Ember.A([])
groupCallback = @get('group')
ungroupedContent = @get('ungroupedContent')
return groupedContent unless groupCallback
return groupedContent unless ungroupedContent
ungroupedContent.forEach (item) ->
group = groupCallback.call(model, item)
return unless groupKey = group.get('key')
foundGroup = groupedContent.findProperty('group.key', groupKey)
unless foundGroup
foundGroup = groupedContent.pushObject Ember.ArrayProxy.create
group: group,
content: Ember.A([])
foundGroup.get('content').pushObject(item)
groupedContent
).property('group', 'ungroupedContent.@each')
控制器用法:
ActivitiesController = Ember.ArrayController.extend Groupable,
ungroupedContentBinding: 'content' # tell Groupable where your default content is
# the callback that will be called for every
# item in your content array -
# just return the same 'key' to put it in the same group
group: (activity) ->
Ember.Object.create
key: moment.utc(activity.get('date')).format('YYYY-MM-DD') # using momentjs to pluck the day from the date
description: 'some string describing this group (if you want)'
模板用法:
{{#each groupedContent}}
{{group.key}} - {{group.description}}
{{#each content}}
Here's the really bad thing that happened: {{message}}
{{/each}}
{{/each}}
基本上,Groupable mixin所做的就是遍历你的普通内容ArrayProxy并调用一个函数来确定它属于哪个组。如果该组对象尚不存在(即未找到匹配的group.key
),则会在将当前内容项添加到组的内容之前创建它。
所以你在模板中最终得到的是一个新的数组(ArrayProxy
)对象(Ember.Object
),每个对象都有一个group
属性(必须至少有)用于标识它的key
属性)和content
属性(包含属于该组的内容)。
答案 1 :(得分:3)
这是一个实现,可在Array
个对象上使用:
var groupByMethod = Ember.Mixin.create({
groupBy: function(key) {
var result = [];
var object, value;
this.forEach(function(item) {
value = item.get ? item.get(key) : item[key];
object = result.findProperty('value', value);
if (!object) {
object = {
value: value,
items: []
};
result.push(object);
}
return object.items.push(item);
});
return result.getEach('items');
}
});
groupByMethod.apply(Array.prototype);
> var posts = [{id: 1, author: 'John'}, {id:2, author: 'Paul'}, {id:4, author: 'Paul'}, {id:5, authour: 'Tom'}];
> posts.groupBy('author')
答案 2 :(得分:3)
您可以像这样使用Ember.computed.groupBy
:
((Ember) ->
# Example:
#
# productsByCategory: Em.computed.groupBy 'products', 'category'
#
# each view.productsByCategory
# category.name
# each content
# content.name
#
Ember.computed.groupBy = (collection, groupBy) ->
dependentKey = "#{collection}.@each.#{groupBy}"
Ember.computed dependentKey, ->
result = []
@get(collection).forEach (item) ->
unless result.findBy groupBy, item.get(groupBy)
data = content: []
data[groupBy] = item.get(groupBy)
result.pushObject Ember.Object.create(data)
result.findBy(groupBy, item.get(groupBy)).get('content').pushObject item
result
) Ember