Reputation: 18929
I have an Angular app with a service and a controller:
service.js
.factory('MyService', function ($http, $q) {
var api_url = 'http://localhost/api/';
var MyService = {
list: function (items_url) {
var defer = $q.defer();
$http({method: 'GET',
url: api_url + items_url}).
success(function (data, status, headers, config) {
defer.resolve(data);
}).error(function (data, status, headers, config) {
defer.reject(status);
});
return defer.promise;
},
...
}
});
controller.js
.controller("ItemsCtrl", function ($scope, MyService) {
$scope.getItems = function () {
MyService.list('items/').then(function(data) {
$scope.items = data;
});
};
$scope.addItems = function () {
$scope.getItems();
// why is this undefined ??!!!
console.log($scope.items);
};
The issue is that I want to call the $scope.getItems
method inside the $scope.addItems
method. Do I perhaps need to use $scope.apply()
, as the returned value is a promise?
I think what I am displaying here is a general lack of understanding.
Upvotes: 0
Views: 2260
Reputation: 43616
Change your controller like this:
.controller("ItemsCtrl", function ($scope, MyService) {
$scope.getItems = function () {
return MyService.list('items/').then(function(data) {
$scope.items = data;
});
};
$scope.addItems = function () {
$scope.getItems().then(function() {
// should be what you want this time
console.log($scope.items);
});
};
Your problem is when you call $scope.getItems()
, http response is not returned yet, so $scope.items
is not populated. You have to wait for all the promises are resolve to access items
.
Upvotes: 3
Reputation:
That is because $scope.getItems
is asynchronous. Your callback (that added via then) is called after $scope.addItems
executed.
Upvotes: 0
Reputation: 211
$scope.items
is undefined because $http
is an asynchronous communication. That is, when you call $scope.addItems()
, it creates and sends the request to retrieve your list of items, then immediately moves on to the next line of code, which is to log $scope.items
to the console. Since there's nothing in $scope.items
yet, you get an undefined value.
If you want to operate on the data returned by the http call, you must guarantee that the data will be populated. In other words, any operations you want to perform on $scope.items
should be called within your .then()
block.
$scope.$apply()
is used when you are not executing within an AngularJS context, to force the AngularJS framework to evaluate the expression. It will not help you here - you'll get an "$digest already in progress" error, or something along those lines.
Try this:
.controller("ItemsCtrl", function ($scope, MyService) {
$scope.getItems = function () {
MyService.list('items/').then(function(data) {
$scope.items = data;
console.log($scope.items);
});
};
$scope.addItems = function () {
$scope.getItems();
};
});
Upvotes: 0