Reputation: 1061
I have an AngularJS application and for some reason one of my forEach
loops are not working. The loop seems to work when the a function on a button click but on the initial load it isn't working.
So I have my controller correctly set up for the page. I am calling a function in my service which fires off to my API and returns me an array:
Controller
var holidaysnew = getUserEventsById.getUserEventsById();
Service
app.service('getUserEventsById', function ($http) {
this.getUserEventsById = function () {
var holidays = [];
$http.get("http://localhost:9847/AceTracker.svc/GetAllEventsByUser?user_id=1").success(function (data) {
for (var key in data.GetAllEventsByUserResult) {
if (data.GetAllEventsByUserResult.hasOwnProperty(key)) {
holidays.push(data.GetAllEventsByUserResult[key])
}
}
});
return holidays;
};
});
So on the initial page load holidaysnew
gets successfully hit and is an array of the holidays. Below the line is where my forEach
loop is, I want to loop through holidaysnew
but it doesn't seem to go into the loop.
The loop is coded as below:
holidaysnew.forEach(function (hol) {
$scope.eventSources[0].events.push({
end: $filter('dateFilter')(hol.HOLIDAY_END),
start: $filter('dateFilter')(hol.HOLIDAY_START),
title: hol.HOLIDAY_TITLE,
color: $filter('colorEventFilter')(hol.HOLIDAY_EVENT_STATE_ID)
});
});
I have console.log
the holidaysnew
array and it definitely getting populated. Can anyone see the issue?
EDIT:
The service seems to be fine and return back the array as expected (See below)
But when the $scope.eventSources[0].events = holidayEvents;
code gets run it doesn't actually seem to set the events.
Is holidayEvents
an array?
EDIT2:
Here is a sample of the JSON returned to the service:
{"GetAllEventsByUserResult":[{"HOLIDAY_END":"\/Date(1456358400000+0000)\/","HOLIDAY_EVENT_ID":1,"HOLIDAY_EVENT_STATE_ID":1,"HOLIDAY_START":"\/Date(1455926400000+0000)\/","HOLIDAY_TITLE":"Spain ","USER_ID":1},{"HOLIDAY_END":"\/Date(1454371200000+0000)\/","HOLIDAY_EVENT_ID":2,"HOLIDAY_EVENT_STATE_ID":2,"HOLIDAY_START":"\/Date(1454284800000+0000)\/","HOLIDAY_TITLE":"Italy ","USER_ID":1},{"HOLIDAY_END":"\/Date(1458000000000+0000)\/","HOLIDAY_EVENT_ID":3,"HOLIDAY_EVENT_STATE_ID":1,"HOLIDAY_START":"\/Date(1457568000000+0000)\/","HOLIDAY_TITLE":"Germany ","USER_ID":1},{"HOLIDAY_END":"\/Date(1481068800000+0000)\/","HOLIDAY_EVENT_ID":4,"HOLIDAY_EVENT_STATE_ID":3,"HOLIDAY_START":"\/Date(1480896000000+0000)\/","HOLIDAY_TITLE":"England ","USER_ID":1}]}
Upvotes: 4
Views: 1519
Reputation: 171679
Change service to return the $http
promise but to also to do all the data manipulation you need in the service itself to create the calendar events and return those.
success
is deprecated in favor of using then()
promise chain callbacks
A more conventional approach would look like:
app.service('getUserEventsById', function($http, $q) {
this.getUserEventsById = function() {
var requestPromise = $http.get("url")
.then(function(response) {
var holidays = [];
var results = response.data.GetAllEventsByUserResult
for (var key in results) {
if (results.hasOwnProperty(key)) {
holidays.push(results[key])
}
}
// return holidays array to next `then()`
return holidays;
}).then(function(holidays) {
var holidayEvents = holidays.map(function(hol) {
// make sure to inject `$filter` in service
return {
end: $filter('dateFilter')(hol.HOLIDAY_END),
start: $filter('dateFilter')(hol.HOLIDAY_START),
title: hol.HOLIDAY_TITLE,
color: $filter('colorEventFilter')(hol.HOLIDAY_EVENT_STATE_ID)
}
});
// return the events array to next `then()`
return holidayEvents;
});
// return the `$http` promise to controller
return requestPromise;
};
});
Then in controller all you would need is
getUserEventsById.getUserEventsById().then(function(holidayEvents){
$scope.eventSources[0].events = holidayEvents;
}).catch(function(){
// do something if promise chain has a rejection
})
Upvotes: 1
Reputation: 2961
This looks like an error with handling your REST response. The population of the array is happening after the return statement, as the REST call is asynchronous. Try moving the loop that isn't working into it's own function, and then calling that function inside the REST success callback, or return a Promise and resolve it in the success callback.
Returning a promise:
app.service('getUserEventsById', function ($http, $q) {
this.getUserEventsById = function () {
var deferred = $q.defer();
var holidays = [];
$http.get("http://localhost:9847/AceTracker.svc/GetAllEventsByUser?user_id=1").then(function (data) {
for (var key in data.GetAllEventsByUserResult) {
if (data.GetAllEventsByUserResult.hasOwnProperty(key)) {
holidays.push(data.GetAllEventsByUserResult[key])
}
}
deferred.resolve(holidays);
});
return deferred.promise;
};
});
Looping on the promise:
holidaysnew.then(function(holidays) {
holidays.forEach(function (hol) {
$scope.eventSources[0].events.push({
end: $filter('dateFilter')(hol.HOLIDAY_END),
start: $filter('dateFilter')(hol.HOLIDAY_START),
title: hol.HOLIDAY_TITLE,
color: $filter('colorEventFilter')(hol.HOLIDAY_EVENT_STATE_ID)
});
});
});
Upvotes: 1
Reputation: 23622
A better solution/approach would be to make your api
call from resolve
.
angular
.module('app')
.config(config);
function config($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'yourTemp.html',
controller: 'Main',
controllerAs: 'vm',
resolve: {
getUserEventsById: function(getUserEventsById){
return getUserEventsById.getUserEventsById()
}
}
});
}
angular
.module('app')
.controller('Main', Main);
Main.$inject = ['getUserEventsById'];
function Main(getUserEventsById) {
var vm = this;
vm.yourdata = getUserEventsById.data;
}
Now you could run your forEach
loop on vm.yourdata
, which would run fine.
Upvotes: 0