【问题标题】:Ember.js Grouping ResultsEmber.js 分组结果
【发布时间】:2014-02-04 07:13:27
【问题描述】:

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

【问题讨论】:

    标签: ember.js


    【解决方案1】:

    这是我稍作调整的 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 属性(包含属于该组的内容)。

    【讨论】:

    • 代码看起来很棒 - 但出现错误:foundGroup = groupedContent.findProperty('group.key', groupKey) groupedContent 没有方法“findProperty”。不知道为什么,因为 groupedContent 正在返回一个 Ember 对象......
    • 嗯,很有趣。在控制台中输入 Ember.A([]).findProperty 会返回任何内容吗?
    • 确实如此 - 但是 ActivitiesController 上的 group() 函数返回的是一个对象,而不是一个可枚举的对象。这就是为什么没有 findProperty。我应该使用其他东西吗?
    • findProperty 在groupedContent 上被调用,它应该只是一个数组。在我的项目中,这一切都按预期工作 - 你可以在 jsfiddle 上发布你的代码吗?
    • 很抱歉 - 您的代码运行良好。我打错字并将错误的内容分配给 groupedContent。谢谢!!
    【解决方案2】:

    这是一个实现,在 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')
    

    【讨论】:

      【解决方案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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-01
        • 1970-01-01
        • 2017-01-17
        • 2013-05-28
        相关资源
        最近更新 更多