-
Notifications
You must be signed in to change notification settings - Fork 331
Common Questions
Ilya edited this page Sep 5, 2017
·
1 revision
- How to use orderBy with groupBy ?
- How to filter (key, value) with ng-repeat ?
- How can I inject specific filter to controller / service ?
- How can I extend or override existing filters ?
Question: how to use orderBy with groupBy ?
See: issue #26
$scope.groups = [
{ category: 'alpha', id: 2 },
{ category: 'beta', id: 3 },
{ category: 'gamma', id: 0 },
{ category: 'alpha', id: 4 },
{ category: 'beta', id: 5 },
{ category: 'gamma', id: 1 }
];
// retrieves the min 'id' of a collection, used for the group ordering.
//you can use lodash instead. e.g: _.min(arr, 'id')
$scope.min = function(arr) {
return $filter('min')
($filter('map')(arr, 'id'));
}
<ul ng-repeat="group in groups | groupBy:'category' | toArray:true | orderBy:min">
<!-- print the group name -->
<li>{{ group.$key }}</li>
<!-- iterate over the group members and order each group by id -->
<li ng-repeat="item in group | orderBy:'id'">
{{ item }}
</li>
</ul>
<!--RESULT:
- gamma
- {"category":"gamma","id":0}
- {"category":"gamma","id":1}
- alpha
- {"category":"alpha","id":2}
- {"category":"alpha","id":4}
- beta
- {"category":"beta","id":3}
- {"category":"beta","id":5}
Question: how to filter (key, value) with ng-repeat ?
See: issue #29 or stackoverflow question
angular.module('app', ['angular.filter'])
.controller('MainCtrl', function($scope) {
//your example data
$scope.items = {
'A2F0C7':{ secId:'12345', pos:'a20' },
'C8B3D1':{ pos:'b10' }
};
//more advantage example
$scope.nestedItems = {
'A2F0C7':{
details: { secId:'12345', pos:'a20' }
},
'C8B3D1':{
details: { pos:'a20' }
},
'F5B3R1': { secId:'12345', pos:'a20' }
};
});
<b>Example1:</b>
<p ng-repeat="item in items | toArray: true | pick: 'secId'">
{{ item.$key }}, {{ item }}
</p>
<b>Example2:</b>
<p ng-repeat="item in nestedItems | toArray: true | pick: 'secId || details.secId'">
{{ item.$key }}, {{ item }}
</p>
Usage: <name>Filter
Example: maxFilter
uniqFilter
angular.module('app', ['angular.filter'])
.controller('MainCtrl', function($scope, maxFilter) {
$scope.list = [1,23,100,64,-79];
$scope.max = maxFilter($scope.list);
//...
})
//or
.factory('SomeFactory', function($filter) {
var maxFilter = $filter('max');
//...
});
You can extends existing filter by using the decorator, see quick example:
angular.module('app', ['angular.filter'])
.controller('MainCtrl', function($scope) {
$scope.players = [
{name: 'Gene', team: 'alpha'},
{name: 'George', team: 'alpha'},
{name: 'Steve', team: 'gamma'},
{name: 'Paula', team: 'alpha'},
{name: 'Scruath', team: 'gamma'},
{name: 'Ariel', team: 'beta'},
{name: 'Mani', team: 'gamma'},
{name: 'Dan', team: 'beta'},
{name: 'Jhon', team: 'gamma'}
];
})
.config(['$provide', function($provide) {
$provide.decorator('countByFilter', ['$delegate', function($delegate) {
//get the source filter function
var srcFilter = $delegate;
var extendsFilter = function() {
//srcFilter result
var srcResult = srcFilter.apply(this, arguments);
//if there is another arguments, we actually want to return the output
return !arguments[2] ? srcResult : sortByVal(srcResult);
};
//get an object and return it sorted
function sortByVal(obj) {
var result = {};
Object.keys(obj)
.sort(function(b,c) {
return obj[b] > obj[c] ? 1 : -1;
})
.forEach(function(key) {
result[key] = obj[key];
});
return result;
}
//we return the extends filter function
return extendsFilter;
}]);
}]);
<body ng-app="app" ng-controller="MainCtrl">
<p>{{ players | countBy: 'team' }}</p>
<b>Sorted list:</b>
<p>{{ players | countBy: 'team': true }}</p>
</body>