I have an angular app, using $resource, that has some factories that use a Rest API for some calls.
The scenario is to get the following three objects: 1) Project, 2) the Project Items and 3) the Project Item Details.
All three objects are defined as 3 different factories and are executing correctly if i try them one by one. However, I am trying to load a page with all the three factories at once.
I have tried several different methods but all fail. The problem is that the factory ProjectItemDetails has dependency on the parent factory data, which is not available at the time of execution.
Factories
angular.module('myProject')
.factory ('Project', function($resource) {
return $resource('api/project/:id', {id: '@id'});
})
.factory ('ProjectItems', function($resource) {
return $resource('api/projectitems/:id', {id: '@id'});
})
.factory ('ProjectItemDetails', function($resource) {
return $resource('api/projectitemdetails/:id', {id: '@id'});
});
Project and ProjectItems request the same ID but ProjectItemDetails requests the detail_id found within each ProjectItem.
Now, additionally, for each ProjectItem I would like to perform a sum operation on a specific field (amount) that is found in the ProjectItemDetails. i.e. one ProjectItem has 3 detail records and each record has an amount of 150, i would like to add a field in each ProjectItem that displays the sum of these details (450).
From the backend I see that all API's are executed, the problem is getting the data back to angular.
Controller
angular.module('myProject')
.controller('SingleController', function($scope, Project, ProjectItems, ProjectItemDetails, $rootScope, $location, $routeParams) {
$scope.project = Project.query({id: parseInt($routeParams.id, 10)});
ProjectItems({id: parseInt($routeParams.id, 10)}, function(data) {
$scope.projectitems = data;
for (var i=0; i < $scope.projectitems.length; i++) {
ProjectItemDetails.query({id: parseInt($scope.projectitems[i][“itemid”])}, function(data){
$scope.projectitems[i].details = data;
var amnt = 0;
for (var j = 0; j < $scope.projectitems[i].details.length; j++) {
amnt += $scope.projectitems[i].details[j].AMOUNT;
};
});
};
});
I get an error when assigning the data to projectitem "TypeError: Cannot set property 'details' of undefined" After a lot of searching it seems that the "i" is out of bounds i.e. I have 3 items (0,1,2), and i is 3.
Can anyone help?
You are running into a variant of this:
javascript-closure-inside-loops-simple-practical-example
By the time ProjectItemDetails.query resolves and you are inside its function, i is 3.
Try invoking ProjectItemDetails.query from a new function, where you pass i as a parameter to the function.