Using Lo-Dash to Get REST Return Amount in AngularJS Application
Scroll down for solutions!
I have a simple AngularJS app (with lodash loaded after angular.js, before app.js):
- Project list page (/ projects), where the link to the item outputs it to / projects /: id
- In / projects /: id the controller executes an API get request and returns data
- I am assigning data to the $ scope.project object and displaying it in the view
Here's an example of the return I get from the API:
{
"_id" : { "$oid" : "546a3bdee4b0bfd97138fe08"} ,
"picture" : "http://placehold.it/400x400" ,
"name" : "Square Campus" ,
"address" : "293 Grafton Street, Shasta, Arizona, 6757" ,
"phone" : "+1 (916) 544-2274" ,
"buildings" : [
{ "name" : "North Campus" , "floors" : "4" , "users" : "8"} ,
{ "name" : "South Campus" , "floors" : "2" , "users" : "15"} ,
{ "name" : "East Wing" , "floors" : "8" , "users" : "23"}
]
}
// Using this call in the controller
$scope.project = Restangular.one('projects', $routeParams.projectId).get().$object;
And this is how I display it in the view:
<aside class="aside-primary col-xs-12 col-md-3">
<div class="well">
<img ng-src="{{project.picture}}" alt="" class="img-responsive"/>
<strong>{{project.name}}</strong><br />
{{project.address}}<br />
{{project.phone}}<br />
</div>
</aside>
<section class="primary-content col-xs-12 col-md-9">
<h1>{{project.name}}</h1>
<h2>Buildings</h2>
<table class="table table-hover table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Floors</th>
<th>Users</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="building in project.buildings">
<td>{{building.name}}</td>
<td>{{building.floors}}</td>
<td>{{building.users}}</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</section>
Now, here's what I want to do:
I am new to Lo-Dash (and JS development is not my strongest asset) and would like to use it to calculate amounts. In this case, the sum of the total number of floors and users.
The problem is, I don't know how to convert the object I get to this array:
// Floors example
var sum = _.reduce([4, 2, 8], function(sum, num) {
return sum + num;
});
console.log(sum);
Can anyone help me figure this out?
Thank!
Decision
It is important that when you make a Restangular call, you are defining a "then" promise, because at first the data is not loaded on the start page.
var detailProject = Restangular.one('projects', $routeParams.projectId);
detailProject.get().then(function (project) {
$scope.project = project; // Assign the owner to a model
var sums = _.reduce(project.buildings,
function (sums, building) {
return {
floors: sums.floors + parseInt(building.floors),
users: sums.users + parseInt(building.users)
};
},
{ floors: 0, users: 0 } // initial values
);
console.log(sums);
});
source to share
If you want to calculate genders and users at the same time, instead of reprocessing the data twice, you can do it like this:
var sums = _.reduce( $scope.project.buildings,
function(sums, building) {
return { floors: sums.floors + parseInt(building.floors),
users: sums.users + parseInt(building.users) };
},
{ floors: 0, users: 0 } // initial values
);
console.log(sums);
// => { floors: 14,
// users: 46 }
You can assign this to a property on your object $scope.project
to display it in the view:
$scope.project.buildingTotals = _.reduce( $scope.project.buildings, // ...
... then ...
<tr>
<td><strong>Total</strong></td>
<td>{{project.buildingTotals.floors}}</td>
<td>{{project.buildingTotals.users}}</td>
</tr>
source to share
Try it. First use pluck to get only gender values, then use shorthand.
You should also work to count your users with minor changes. ParseInt is needed because your numbers are strings, so using plus will concatenate them rather than appending without it.
var sumFloors = _.pluck(project['buildings'], 'floors').reduce(function(previous, current){
return parseInt(previous, 10) + parseInt(current, 10);
});
source to share