Ember.js分组结果

时间:2014-01-15 17:09:42

标签: ember.js

我正在尝试在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。

3 个答案:

答案 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')

usage example

答案 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