在AngularJS ng-repeat中对集合进行分组?

时间:2012-12-28 16:30:09

标签: angularjs taffydb

我有一个非常简单的场景,其中有一组记录可供使用,我需要在简单的ng-repeat中显示它们。但是我需要按属性分组的记录,我的目标不是不必更改集合以完成此分组。我的想法是可以应用某种类型的过滤器,但在实践过滤器,过滤器,数据和不分组。有没有办法有一个集合,只是分组和重复?

非常hack-ish jsFiddle与我正在尝试做的事情在这里。

http://jsfiddle.net/bryangrimes/RufQh/5/

总之,这个想法是:

<ul>
      <li ng-repeat="log in logs grouped by log.dept">
        <h4>{{log.dept}}</h4>
        {{log.name}} worked {{log.hours}} this week
      </li>            
  </ul>

更新: 所以最后我们已经使用taffyDB来存放原始数据集,所以这只是扩展了。

$.each($scope.logs, function() {
        var log = $(this)[0];

        // build angular friendly data structure
        log.workLogsDB = TAFFY(log.worklogs);
        log.deptLogs   = [];

        $.each(log.workLogsDB().distinct('department').sort(), function() {
            var dept  = $(this)[0].toString();
            var cost  = log.workLogsDB({department:dept}).sum('cost');
            var hours = log.workLogsDB({department:dept}).sum('hours');
            var items = log.workLogsDB({department:dept}).get();

            log.deptLogs.push({
                department: dept,
                total_cost: cost,
                total_hours: hours,
                line_items: items
            });
        });
    });

和要呈现的HTML:

<div ng-repeat="log in logs">
                <h3 onclick="$('#{{log.project}}').slideDown()">    
                    {{log.project}} hours:{{log.hours}} cost: ${{log.cost}}
                </h3>
                <ul id="{{log.project}}" style="display: none;">
                    <div ng-repeat="log in log.deptLogs">
                        <span style="font-weight: bold; text-transform: capitalize;">{{ log.department }} - Team Cost: ${{ log.total_cost }}, Team Hours: {{ log.total_hours }} </span>
                        <li ng-repeat="line in log.line_items">
                            {{line.employee}} {{line.hours}} hours
                        </li>
                        <br>
                    </div>
                </ul>
            </div>

3 个答案:

答案 0 :(得分:7)

我认为你需要创建一个集合的排序副本,然后对该排序集合进行ng-repeat。这是a fiddle我刚才有人问过类似的问题。突出点:

function MyCtrl($scope, orderByFilter) {  // inject orderByFilter
   $scope.sortedLogs = orderByFilter($scope.logs, '+dept');
}

HTML:

<ul>
  <li ng-repeat="log in sortedLogs">
      <ng-switch on="$first || log.dept != sortedLogs[$index-1].dept">
          <div ng-switch-when="true" class="group"><h4>{{log.dept}}</h4>
      </ng-switch>
      {{log.name}} worked {{log.hours}} this week
  </li>
</ul>

答案 1 :(得分:1)

我喜欢马克的回答,我的策略通常是重新整理收藏品,以便让渲染变得更容易。

这是一个显示方法http://jsfiddle.net/RufQh/12/

的小提琴
var sorted = [];
logs.forEach(function(log){if (!sorted[log['dept']]) {sorted[log['dept']]= []} sorted[log['dept']].push(log);})

$scope.depts=[];
for(var dept in sorted) {
    $scope.depts.push({name:dept,items:sorted[dept]});
}

一旦我有了这个,那么我将渲染w /嵌套循环

<li ng-repeat="dept in depts">{{dept.name}}<br/> 
          <ul>
              <li ng-repeat="log in dept.items">{{log.name}} worked {{log.hours}} this week as a(n) {{log.dept}}</li>
          </ul>
  </li>

使用map / reduce或taffyBD之类的框架可以更轻松地转换数据。这种方法的缺点是多次传递数据(而不是单一种类)以及增加的角度范围创建。

好处是,在控制器中组织内容可能更容易。

答案 2 :(得分:0)

您已经在使用taffydb作为数据,因此它可能与您无关,但是其他想要这样做的人可能会发现使用ForerunnerDB(http://www.forerunnerdb.com),因为它具有类似MongoDB的高级查询并且还支持数据视图,以便您可以按查询过滤集合并从中生成视图。

视图包含来自基础集合的最新过滤数据,如果集合中的数据发生更改,则视图也会自动更新。