muudless
muudless

Reputation: 7532

Problems using $http inside a Service

I have a basic data Service which will be used across Controllers. But I'm having an issue grabbing some data that's been added via $http.

Service:

angular.module('core').service('FormService', ['$http', function($http) {
    var _this = this;
    _this.dropdownData = {
        contactTimes: ['Anytime','Morning','Afternoon','Evening'],
        industries: {},
    };

    $http.get('/json').success(function(resp){
        _this.dropdownData.industries = resp.industries; 
    });
}]);

Controller:

angular.module('core').controller('SignupController', ['$scope', '$http', '$state', 'FormService', function($scope, $http, $state, FormService) {

    console.log(FormService.dropdownData); // Shows full object incl industries
    console.log(FormService.dropdownData.industries); // empty object {}

}]);

How do I get FormService.dropdownData.industries in my controller?

Upvotes: 0

Views: 1115

Answers (5)

Michael Kang
Michael Kang

Reputation: 52847

The industries object will be populated at a later point in time when the $http call returns. In the meantime you can still bind to the reference in your view because you've preserved the reference using angular.copy. When the $http call returns, the view will automatically be updated.

It is also a good idea to allow users of your service to handle the event when the $http call returns. You can do this by saving the $promise object as a property of industries:

angular.module('core').service('FormService', ['$http', function($http) {
    var _this = this;
    _this.dropdownData = {
        contactTimes: ['Anytime','Morning','Afternoon','Evening'],
        industries: {},
    };

    _this.dropdownData.industries.$promise = $http.get('/json').then(function(resp){
               // when the ansyc call returns, populate the object, 
               // but preserve the reference
               angular.copy( resp.data.industries, _this.dropdownData.industries); 
               return _this.dropdownData.industries;
           });


}]);

Controller

    app.controller('ctrl', function($scope, FormService){
              // you can bind this to the view, even though the $http call has not returned yet
              // the view will update automatically since the reference was preserved
              $scope.dropdownData = FormService.dropdownData;

              // alternatively, you can hook into the $http call back through the $promise
              FormService.dropdownData.industries.$promise.success(function(industries) {
                     console.log(industries);
              });
    });

Upvotes: 0

CozyAzure
CozyAzure

Reputation: 8478

Given that your console log shows the correct object, that shows your service is functioning properly. Only one small mistake you have made here. You need to access the data attributes in your return promise.

angular.module('core').service('FormService', ['$http', function($http) {
  var _this = this;
  _this.dropdownData = {
     contactTimes: ['Anytime','Morning','Afternoon','Evening'],
     industries: {},
 };

 $http.get('/json').success(function(resp){
    //note that this is resp.data.industries, NOT resp.industries
    _this.dropdownData.industries = resp.data.industries; 
   });
 }]);

Upvotes: 1

Seminda
Seminda

Reputation: 1773

Add a method to your service and use $Http.get inside that like below

_this.getindustries = function (callback) {
        return $http.get('/json').success(function(resp){
            _this.dropdownData.industries = resp.industries; 
            callback(_this.dropdownData)
      });
    };

In your controller need to access it like below.

 angular.module('core').controller('myController', ['$scope', 'FormService', function ($scope, FormService) {
   FormService.getDropdownData(function (dropdownData) {
       console.log(dropdownData); // Shows full object incl industries
       console.log(dropdownData.industries); // object {}
   });

} ]);

Upvotes: 1

Nitin Chaurasia
Nitin Chaurasia

Reputation: 263

Create a service like below

appService.factory('Service', function ($http) {
        return {
            getIndustries: function () {
                return $http.get('/json').then(function (response) {
                    return response.data;
                });
            }
        }
    });

Call in controller

appCtrl.controller('personalMsgCtrl', ['$scope', 'Service', function ($scope, Service) {
    $scope.Industries = Service.getIndustries();
}]);

Hope this will help

Upvotes: 3

Wottensprels
Wottensprels

Reputation: 3327

Assuming that you're data is indeed existing and there are no problems with the server, there are quite a few possible solutions

Returning a promise

angular.module('core').service('FormService', ['$http', function($http) {
  var _this = this;
  _this.dropdownData = {
    contactTimes: ['Anytime','Morning','Afternoon','Evening'],
    industries: {},
  };

  _this.dropdownData.industries = $http.get('/json');
}]);

//Controller
FormService.industries
.then(function(res){
    $scope.industries = res.industries
});

Resolving with routeProvider / ui-route

See: $http request before AngularJS app initialises?


You could also write a function to initialize the service when the application starts running. At the end of the day, it is about waiting for the data to be loaded by using a promise. If you never heard about promises before, inform yourself first.

Upvotes: 0

Related Questions