A. Davidsson
A. Davidsson

Reputation: 27

Passing data from Service AngularJS

Dear all I am having trouble with the scope of my $scope or how should I put it.

I am retrieving the data from my Service successfully but I´m having trouble with accessing $scope.players and $scope.tournament and I think it has something to do with being inside the service call. If I console.out() inside the service call everything is just fine. How can I be able access the data which is inside of the service call.

Version 1: Here console log simply states undefined.

.controller('SelectCtrl', ['$scope','$stateParams', '$location', '$window','playerService','tournamentService', function ($scope, $stateParams, $location, $window, playerService, tournamentService) {

     init();
     function init() {

         playerService.getPlayers().then(function (data) {
             $scope.players = [];
             angular.forEach(data, function (player, index) {
                 $scope.players.push(player.info);
             });
         });

         tournamentService.getTournaments().then(function (data) {
             var result = data.filter(function (element) {
                 if (element.ID == $stateParams.id) {
                     return true;
                 } else {
                     return false;
                 }
             });
             $scope.tournament = result;
         });
     };

     console.log($scope.tournament);//undefined
     console.log($scope.players); //undefined
}

Version 2:, Here console log simply states the Object {then: function, catch: function, finally: function} Which is not what I wan´t I want the data to be able to display it in my view.

.controller('SelectCtrl', ['$scope','$stateParams', '$location', '$window','playerService','tournamentService', function ($scope, $stateParams, $location, $window, playerService, tournamentService) {

     init();
     function init() {

         $scope.players = playerService.getPlayers().then(function (data) {
             $scope.players = [];
             angular.forEach(data, function (player, index) {
                 $scope.players.push(player.info);
             });
         });

        $scope.tournament = tournamentService.getTournaments().then(function (data) {
             var result = data.filter(function (element) {
                 if (element.ID == $stateParams.id) {
                     return true;
                 } else {
                     return false;
                 }
             });
             $scope.tournament = result;
         });
     };

     console.log($scope.tournament);//Object {then: function, catch: function, finally: function}

     console.log($scope.players);//Object {then: function, catch: function, finally: function}

}

Your help is really appreciated!

The Services:

.factory('playerService', function ($http,$q) {
    return {
        getPlayers: function () {
            //return the promise directly.
            var deferred = $q.defer();
            $http.get(webServiceUrl + 'api/Player/GetAllPlayers')
                      .success(function (data) {
                          //resolve the promise as the data
                          deferred.resolve(data);
                      }).error(function () {
                          deferred.reject();
                      });
            return deferred.promise;
        }
    }

})

.factory('tournamentService', function ($http,$q) {
    return {
        getTournaments: function () {
            //return the promise directly.
            var deferred = $q.defer();
            $http.get(webServiceUrl + 'api/Tournament/GetAllTournaments')
                      .success(function (data) {
                          //resolve the promise as the data
                          deferred.resolve(data);
                      }).error(function () {
                          deferred.reject();
                      });
            return deferred.promise;
        }
    }

})

Part of the view:

  <h1 style="display: inline-block; margin-left:15px;">Enter <i>{{tournament.Name}}</i></h1>
        <div class="row">
            <div class="selectinforow">
                <div class="col-xs-2 selectinfo">
                    <span>{{tournament.EntryFee}}$</span></br>
                    <span>Entry Fee</span>
                </div>
                <div class="col-xs-2 selectinfo">
                    <span>{{tournament.Entries}}</span></br>
                    <span>Entries</span>
                </div>
                <div class="col-xs-2 selectinfo">
                    <span>{{tournament.Size}}</span></br>
                    <span>Max Size</span>
                </div>
                <div class="col-xs-2 selectinfo">
                    <span>{{tournament.StartTime}}</span></br>
                    <span>Start Date</span>
                </div>
                <div class="col-xs-2 selectinfo">
                    <span>{{tournament.Entryfee*tournament.Entries}}$</span></br>
                    <span>Winnings</span>
                </div>
            </div>
        </div>

Upvotes: 0

Views: 653

Answers (2)

Paul Rad
Paul Rad

Reputation: 4882

Your code is executed before the promise response.

If you need to code "procedurally", you should $watch the scope variable as below to detect any changes.

For example:

$scope.$watch('tournament', function() {
 console.log($scope.tournament);
}, true);

Upvotes: 0

drew_w
drew_w

Reputation: 10430

So if you read your code carefully you will notice you are using a promise on the following line:

tournamentService.getTournaments().then(function (data) {
   // [your data is set here - AFTER the service call runs]
}

// [your print is here - run BEFORE service call runs]

The key to the "then" statement is it isn't executed right away, but is instead run when data is returned from the service call. In other words, you have your print in the wrong spot - I would expect the values to be undefined there. If you move the console.log statements into the promise (then) - I would expect to see the valid values. You can also put a break point in the browser debugger to see the values in the "then" function if you want to validate that things are working. Hope this puts you on the right track!

EDIT

Once the promise completes, angular automatically updates the view. Lets say you have the following in your view (just an example):

<h1 ng-bind="tournament.Title">Default Text</h1>

When the view/page loads you will see "Default Text". After the promise completes, if a tournament has been loaded, angular will automatically update the "h1" to now have the Title for that tournament. This happens because angular automatically runs an "$apply()" after a promise completes.

Upvotes: 2

Related Questions