Reputation: 3673
In angular JS, I have a variable that keeps track of people and their age
$scope.people = [
{
name: "Lucy",
age: "18"
}, {
name: "Michael",
age: "24"
}, {
name: "Lisa",
age: "46"
}
];
The user can add more people via a simple form:
<input ng-model="newPerson.name">
<input ng-model="newPerson.age">
<button ng-click="addNewPerson()">Add</button>
At the bottom of the page, I want a simple pie graph showing the population by age group eg.(>18, 18-25, 26-35, 36-45, 45<). To do that, I need to be able to filter the $scope.people
by age, get the number of each group.
I know I could use normal javascript to loop through the whole array, get a count of each age group. And whenever a new person is added, just increment the count in that particular group, but I was wondering if there is a more efficient and angular-esque way to do this?
Upvotes: 0
Views: 155
Reputation: 1712
Here's one way to implement this with Array.Prototype.filter and Array.Prototype.reduce. Note the the filter is applied on $scope.ageBrackets
which contains the pre-processed data prepared by the forEach
loop. This is efficient for small range values such as the age of a person. This is one alternative if you are not using ng-repeat
and you don't want to filter the data multiple times.
angular.module('ageBracketApp', ['ageBracketApp.controllers']);
angular.module('ageBracketApp.controllers', []).controller('ageBracketController', ['$scope',
function($scope) {
$scope.ageBrackets = [];
$scope.people = [{
name: "Lucy",
age: "18"
}, {
name: "Michael",
age: "24"
}, {
name: "Lisa",
age: "46"
}];
angular.forEach($scope.people, function(value, key) {
$scope.ageBrackets[value.age] = $scope.ageBrackets[value.age] + 1 || 1;
});
$scope.addPerson = function() {
var age = Math.floor(Math.random() * (123 - 1 + 1)) + 1; // random between 1 and 123
$scope.people.push({
name: 'Person ' + ($scope.people.length + 1),
age: age
});
$scope.ageBrackets[age] = $scope.ageBrackets[age] + 1 || 1;
};
$scope.ageBracketCount = function(min, max) {
max = max || Number.MAX_SAFE_INTEGER;
return $scope.ageBrackets.filter(function(value, index, array) {
return index >= min && index <= max;
}).reduce(function(a, b) {
return a + b;
}, 0);
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ageBracketApp" ng-controller="ageBracketController">
{{people}}
<hr />18+: {{ageBracketCount(18)}}
<br />18-25: {{ageBracketCount(18,25)}}
<br />26-35: {{ageBracketCount(26,35)}}
<br />40-: {{ageBracketCount(0,40)}}
<hr />
<button ng-click="addPerson()">
Add person
</button>
</div>
Upvotes: 1
Reputation: 10515
You can use a library like lodash: _($scope.people).filter(x => x.age > 18 && x.age <= 25).count()
Alternatively, if you are already using the filtered list in an ng-repeat you can assign it as a variable and get the length e.g.:
<ul>
<li ng-repeat="item in people | filter:filterFunction as results"></li>
</ul>
<p>{{results.length}}</p>
function filterFunction(item) {
return item.age > 18 && item.age <= 25;
}
Upvotes: 1