1

I'm having difficulty returning data from my service to my view in AngularJS. Here is what I have at the moment. I also tried something like this, but had the same result. AngularJS Load Data from Service

Controller

.controller('ClassCtrl', ['$scope', '$stateParams', 'ClassService', function($scope, $stateParams, ClassService) {
        $scope.data = ClassService.getClass($stateParams.siteID, $stateParams.classDate, $stateParams.classID);
        $scope.$apply(); // I thought this my do it?
    }])

Service

.factory('ClassService', ['$http', function ($http) {
        return {
            getClass: function(parm1, parm2, parm3) {
                var classData = {};

                var url = 'http://somesoapservice.com';
                var sr = '<?xml version="1.0" encoding="UTF-8"?>' +
                    '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +
                    'moresoapstuff' +
                    '</soap:Body>' +
                    '</soap:Envelope>';

                $http({
                    method: 'POST',
                    url: url,
                    data: sr,
                    headers: {
                        'Content-type': 'text/xml',
                        'SOAPAction': 'http://somesoapservice/soapaction'
                    }
                }).
                success(function (data, status, headers, config) {
                    var classDetail = $(data).find('Class');
                    var staffFirst = classDetail.find('Staff').find('FirstName').text();

                    //alert(staffFirst); // This displays the first name. Great!

                    classData = {
                        staffFirst: staffFirst
                    };

                    return classData;
                }).
                error(function(data, status, headers, config) {
                    alert('Error!');
                });

                return classData;
            }
        }
    }])

View

<view title="navTitle" right-buttons="rightButtons">
    <content has-header="true" has-footer="true">
    First Name: {{data.staffFirst}}
    </content>
</view>

I can see staffFirst in an alert when put inside the service, but cannot get it to appear in my view. enter image description here

1
  • 1
    See answers here,here or here Commented Jan 24, 2014 at 16:50

1 Answer 1

1

I've just started learning AngularJS and this was one of those gotcha's that I missed coming from a desktop synchronous-based development background.

The issue here is that your $Http call within your service is firing off asynchronously. Thus your code line return classData; at the end of your getClass is going to return before the $Http call. Therefore only the empty initialised value ({}) of your object will be returned and that's all your view will have to access.

What you need, is to hook into the promise capability of the Angular framework. A promise essentially allows you to place a method callback on itself so that when an asynchronous operation is complete, your code logic is assured to fire in a synchronous manner.

Your code would need to change as follows:

We first need to inject the promise library into your factory

.factory('ClassService', ['$http','$q' function ($http, $q) {

Your factory return will be:

getClass: function(parm1, parm2, parm3) {
  var classData = {};

  var url = 'http://somesoapservice.com';
  var sr = '<?xml version="1.0" encoding="UTF-8"?>' +
           '<soap:Envelope 
            xmlns:soap="http://schemas.xmlsoap.org/soap
            /envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +
           'moresoapstuff' +
           '</soap:Body>' +
           '</soap:Envelope>';

           var deferred = $q.defer(); // our promise object

           $http({
                method: 'POST',
                url: url,
                data: sr,
                headers: {
                    'Content-type': 'text/xml',
                    'SOAPAction': 'http://somesoapservice/soapaction'
                }
            }).
            success(function (data, status, headers, config) {
                var classDetail = $(data).find('Class');
                var staffFirst = classDetail.find('Staff')
                                 .find('FirstName').text();

                //alert(staffFirst); // This displays the first name. Great!

                classData = {
                    staffFirst: staffFirst
                };
                deferred.resolve(classData); //At this point our promise is "resolved"
                return deferred.promise;
            }).
            error(function(data, status, headers, config) {
                deferred.reject("Error!");
                return deferred.promise;
            });
            }

Your controller

.controller('ClassCtrl', ['$scope', '$stateParams', 'ClassService', function($scope, $stateParams, ClassService) {           
   ClassService.getClass($stateParams.siteID, $stateParams.classDate,    $stateParams.classID)
  .then(function(data){ 
    $scope.data = data; //This callback will only execute once the $http success has   completed.
  })
  .fail(function(error){
    alert(error);
  });

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.