0

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.

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

Comments

0

$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();
  };
});

Comments

0

That is because $scope.getItems is asynchronous. Your callback (that added via then) is called after $scope.addItems executed.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.