0

I have a service in angular JS which is defined as follows:

'use strict';

angular.module('Offering.AccountService', [])

.service('Account', function($http, config) {

    var account = this;

    account.accountDetails = {};

    this.getAccountDetails = function(){
        var request = $http({
            method: 'GET',
            url: config.accountURL,
            headers: {
                'X-Parse-Application-Id': config.applicationID,
                'X-Parse-REST-API-Key': config.restAPIKey,
            }
        })
        .success(function(data, status, headers, config) {
            console.log('Successfully aqquired account details');
            account.accountDetails = data.results[0];

        })
        .error(function(data, status, headers, config) {
            console.warn(status);
        });
    }


});

This service calls out to an endpoint to retrieve some data, I am calling this method in the run function of the main module as is shown below:

'use strict';

angular.module('Offering', [
    'routerRoutes'
])

.run(function(Account){
    Account.getAccountDetails();
})

In my controller, I have a variable called balance, in which I want to store the value retrieved from the service, as is shown in the code below:

'use strict';

angular.module('Offering.HomeController', [])

.controller('HomeCtrl', function(Account) {

    this.data = {
        message: "Account Details",
        updateBalance: function() {
            Account.getAccountDetails()
        },
        balance: Account.accountDetails.balance
    }

    // this.$watch(
    //     function () { return Account.accountDetails; },
    //     function (data) {
    //         $scope.data.balance = data.balance
    //     },
    //     true
    // );
})

The data from the service is returned after the controller data object has been set up and thus the balance field is not getting populated. If I use the $scope.watch approach that is commented out, then the data object gets populated properly. However, I was under the assumption that this need not be done as there is a two way data binding between the service and the controller. Any help is greatly appreciated. Thanks !

1
  • 3
    This is typically handled by returning a promise from your service and setting the data in your controller when the promise is resolved. Commented Feb 23, 2015 at 18:39

2 Answers 2

1

The .run function doesn't stop to wait for the getAccountDetails to return a value. And so, when you assign this.data.balance = Account.accountDetails.balance, you are essentially doing this: this.data.balance = undefined.

As per comment above, the typical way is to have getAccountDetails() to return a promise, like so:

this.getAccountDetails = function(){
   return $http({...})
       .then(function(response){
          console.log("successfully returned balanace", response.data);
          return response.data;
       });
}

Then, in the controller:

var vm = this;
Account.getAccountDetails()
  .then(function(accountDetails){
     vm.balance = accountDetails.balance;
  });
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your response. I did not want to do this in the controller as I would like to use the data returned in multiple controllers. Is there any way I can do this before any of the controllers are set up so that I do not have to do it in every controller?
If you populate, rather than overwrite, the initially-empty accountDetails object, then you could $watch it for changes. However, that is not efficient, as it will be done on every digest. The other way would be to use the resolve property of $routeProvider or the more powerful $stateProvider - this allows you to resolve all the async dependencies prior to navigating to the View, and inject them into all the dependent controllers.
Thank you, this seems to be what I am looking for.
0

You can not put a watch on the function which is returning promise, better you could put watch on this.data, Their is different way of put watch while using this keyword inside controller.

CODE

$scope.$watch(angular.bind(this, function () {
    return this.data; 
  }), function (newVal, oldVal) {
    // now we will pickup changes to newVal and oldVal
  });

Hope this could help you , Thanks.

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.