AngularJS:按记录中某个字段对数据进行分组

8

是否有类似于Angular中的group by功能,可以将这种分组头下的JSON数据进行分组。

外部列表按组对数据进行排序,然后是该组的内部列表数据项,如果可以对这些数据进行分组,则无法理解此数据。

var data = [  
   {  
      "id":23,
      "name":"Fun Run (Pre-Registration Required)",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 7:00 am to 1:45 pm"
   },
   {  
      "id":24,
      "name":"Breakfast",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 7:00 am to 1:45 pm"
   },
   {  
      "id":25,
      "name":"Opening Address",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 7:00 am to 1:45 pm"
   },
   {  
      "id":25,
      "name":"abc",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 1:00 pm to 9:00 pm"
   },
   {  
      "id":26,
      "name":"xyz",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 1:00 pm to 9:00 pm"
   },
    {  
      "id":26,
      "name":"xyz",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 8:45 am to 2:00 pm" //notice a different header
   },
  {  
      "id":26,
      "name":"xyz",
      "date":"Wednesday Nov 12",
      "group_header":"Sessions from 1:30 pm to 11:00 pm" //another different header
   }
]
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<ul>
    <li>Sessions from 7:00 am to 1:45 pm
        <ul>
            <li>Fun Run (Pre-Registration Required)</li>
            <li>Breakfast</li>
            <li>Opening Address</li>
        </ul>
    </li>
    <li>Sessions from 1:00 pm to 9:00 pm
        <ul>
            <li>abc</li>
            <li>xyz Address</li>
        </ul>
    </li>
    <li>another custom header (no pattern to it) - sessions from 10 am to 5 pm 
        <ul>
            <li>abc</li>
            <li>xyz Address</li>
        </ul>
    </li>
</ul>


1
你需要根据你想要排序的方式编写一个过滤器。 - Linial
好的,为了缩小范围,我只需要检查两个值,即7:00 am至1:45 pm的会话和1:00 pm至9:00 pm的会话。需要帮忙吗? - user2727195
2个回答

7

现在可以编写自定义筛选选项,以便创建更复杂的筛选。

第一次编辑: 使用来自angular-filter GitHub的Angular-Filter

这是您请求的工作JSBIN 我正在使用angular-filter,group-by选项,这使我可以这样做。 您可以遵循相当简单的HTML

HTML:

<ul ng-repeat="(key, value) in data | groupBy: 'group_header'"> //First extracting key value, from ng-repeat and grouping it by group_header ( External 3rd party filter by angular-filter).

  Group name: {{ key }}
  <li ng-repeat="item in value"> // Then extra ng-repeat to iterate each of the objects and presenting the name .
    Activity : {{ item.name }} 
  </li>
</ul>

JS:你所需做的只有:

像这样将 angular-filter 注入到您的代码中:

angular.module('app',['angular.filter'])..

我为您的需求编写了一个筛选器,它是量身定制的,同时也可重复使用并且易于测试。

在复制粘贴之前:

了解何时以及如何使用过滤器非常重要。

在我的解决方案中,我编写了一个筛选器,您可以声明一个最小小时数,只有晚于该小时数的小时才会显示。

让我们阅读代码:

app.filter('minHour',function(){ // 1 - Explained below.
  return function(items, minHour){ //2 - Explained below.
    var filtered = [];
    for(var i =0 ; i < items.length ; i ++){
        var hour = parseInt(items[i].start.slice(0,2)); //3 - Explained below.
        if(hour === minHour || hour > minHour){
          filtered.push(items[i]);
        }
    }
    return filtered;
  }
})

我认为上述代码大部分很容易理解,但我将对其中一些难点进行解释:

1)这是Angular定义新过滤器的方式。

2)该过滤器将始终返回一个带参数的函数。第一个参数始终是ng-repeat的项目,第二个参数始终是调用过滤器时要使用的字符串。(这是最重要的一点)。

3)虽然这可以工作,但是警告:这是一种糟糕的做法,因为我在函数中做了太多假设!

* 我假设小时将写在字符串的前两个字母中。

* 我假设小时始终在“start”属性上而没有先检查属性。

* 我假设可以比较这些值。

所以我们需要吸取教训:

在编写过滤器之前,请确保您没有做出太多假设。

始终在测试数据的真实性之前进行测试!

用法+ Plunker:

<ul>
  <li ng-repeat="items in data | minHour:09">{{items.start}}</li>
</ul>

Plunker

我没有编写最大小时过滤器,因为我真的希望你能练习一下。如果你仔细阅读我的答案,它是非常容易的。

如果您有更多问题,我很乐意帮助!


没问题,别犹豫,如果想要尝试看看这段代码的工作原理,只需将html minHour更改为您喜欢的任何内容即可。这是过滤函数中纯JavaScript代码。 - Linial
实际上我意识到了一些事情,我真的不需要检查少于某个小时的内容,我需要整理标题下的数据,我将删除开始和结束字段以避免 JSON 中的混淆,所以它并不是检查小时范围,而是自定义标题,并且在行之间变化,好处是行按 group_header 排序。 - user2727195
这将会大大降低代码的灵活性,因为你可能会有无数个独特的会话。 - Linial
是的,你说得对,这些标题没有规律可言。比如说,有一天可能只有从上午10点到下午2点的会话,所以每天都是定制的。关键是它们都作为一个组出现,接下来的组行将有自己独特的标题,这就是我说类似于在Angular中使用SQL group by的原因。 - user2727195
我看到了这篇帖子,但我真的不太理解,不知道你能否帮忙解释一下:https://dev59.com/L2Ij5IYBdhLWcg3wsnCn - user2727195
@user2727195 已编辑。请查看 JSBIN。 - Linial

1

您可以这样使用angular-filter:

在您的HTML头部中:

<script src="//cdnjs.cloudflare.com/ajax/libs/angular-filter/0.4.7/angular-filter.js">    </script>.

然后在你的Angular应用中声明'angular.filter':

angular.module('project', ['ngRoute','angular.filter']).config(fu....

然后像这样利用:
<tr ng-repeat="(k,v) in data| groupBy: 'group_header'">
    <td>{{k}}</td>
    <td>
        <ul>
            <li ng-repeat="item in v">
                {{item.name}}
            </li>
        </ul>
    </td>
</tr>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接