Darwin Tech
Darwin Tech

Reputation: 18929

Accessing returned scope method variables in another method in AngularJS

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

Answers (3)

Daiwei
Daiwei

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

user2445933
user2445933

Reputation:

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

Upvotes: 0

Dave
Dave

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

Related Questions