我是新来的Angular,并想学习处理一个问题的最佳方式。我的目标是有一个可重用的方法来创建组的头。我创建了一个解决方案,但我认为这应该是一个指令,而不是我的控制器中的范围函数,但我不知道如何完成这一点,或者如果指令是甚至正确的方式去。任何投入将非常感谢。
在HTML中,这是一个使用ng-repeat的简单列表,其中我在ng-show上调用了newGrouping()函数。该函数传递一个引用到完整列表,我想要分组的字段和当前索引。
<div ng-app> <div ng-controller='TestGroupingCtlr'> <div ng-repeat='item in MyList'> <div ng-show="newGrouping($parent.MyList,'GroupByFieldName',$index);"> <h2>{{item.GroupByFieldName}}</h2> </div> {{item.whatever}} </div> </div> </div>
在我的控制器我有我的newGrouping()函数,它只是比较当前的上一个,除了第一个项目,并返回true或false取决于匹配。
function TestGroupingCtlr($scope) { $scope.MyList = [ {GroupByFieldName:'Group 1',whatever:'abc'},{GroupByFieldName:'Group 1',whatever:'def'},{GroupByFieldName:'Group 2',whatever:'ghi'},whatever:'jkl'},whatever:'mno'} ]; $scope.newGrouping = function(group_list,group_by,index) { if (index > 0) { prev = index - 1; if (group_list[prev][group_by] !== group_list[index][group_by]) { return true; } else { return false; } } else { return true; } }; }
输出将如下所示。
第1组
> abc
> def
第2组
> ghi
> jkl
> mno
觉得应该有一个更好的方法。我想这是一个常用的效用函数,我可以重用。这应该是一个指令吗?有没有更好的方法来引用列表中的上一个项目,而不是我的方法传递完整的列表和当前的索引?我将如何处理这个指令?
任何建议都非常感谢。
更新:寻找一个不需要外部依赖的答案。
有很好的解决方案使用下划线/ lodash或角度过滤器模块。
Darryl
这是上面Darryl的解决方案的一个修改,允许多个group by参数。此外,它使用$ parse允许使用嵌套属性作为group by参数。
使用多个嵌套参数的示例
HTML
<h1>Multiple Grouping Parameters</h1> <div ng-repeat="item in MyList | orderBy:'groupfield' | groupBy:['groupfield','deep.category']"> <h2 ng-show="item.group_by_CHANGED">{{item.groupfield}} {{item.deep.category}}</h2> <ul> <li>{{item.whatever}}</li> </ul> </div>
过滤器(Javascript)
app.filter('groupBy',['$parse',function ($parse) { return function (list,group_by) { var filtered = []; var prev_item = null; var group_changed = false; // this is a new field which is added to each item where we append "_CHANGED" // to indicate a field change in the list //was var new_field = group_by + '_CHANGED'; - JB 12/17/2013 var new_field = 'group_by_CHANGED'; // loop through each item in the list angular.forEach(list,function (item) { group_changed = false; // if not the first item if (prev_item !== null) { // check if any of the group by field changed //force group_by into Array group_by = angular.isArray(group_by) ? group_by : [group_by]; //check each group by parameter for (var i = 0,len = group_by.length; i < len; i++) { if ($parse(group_by[i])(prev_item) !== $parse(group_by[i])(item)) { group_changed = true; } } }// otherwise we have the first item in the list which is new else { group_changed = true; } // if the group changed,then add a new field to the item // to indicate this if (group_changed) { item[new_field] = true; } else { item[new_field] = false; } filtered.push(item); prev_item = item; }); return filtered; }; }]);