Stuck: AngularJs using the factory with the HTTP call to JSON

advertisements

I am struck and not able to understand the issue here. I created a factory using http service call to my json file Factory (accountInfo.json):

appRoot.factory('accountInfo', ['$http', function($http) {
  return $http.get('../../accountInfo.json')
    .success(function(data) {
      return data;
    })
    .error(function(err) {
      return err;
    });
}]);

controller(AccountsController.js)

appRoot.controller('AccountsController', ['$scope', 'accountInfo', function($scope, accountInfo){

    accountInfo.success(function(data) {
      $scope.rows = data;
    });

    $scope.totals = {
        name: '',
        marketValue: 0,
        cash: 0,
        legend: 'none'
    };

    for (var i = 0; i < $scope.rows.length; i++) {
        $scope.totals.marketValue += $scope.rows[i].marketValue;
        $scope.totals.cash += $scope.rows[i].cash;
    }

    $scope.addAccount = function() {
        $scope.rows.push({
            name: 'New Account',
            marketValue: Math.random() * 100000,
            cash: Math.random() * 400000,
            legend: 'cyan'
        });
    }
}]);

My json (accountInfo.json)

[{
    "name": "Brokerage Account 3",
    "marketValue": 1999990,
    "cash": 1995826,
    "legend": "orange"
},
{
    "name": "Account 3",
    "marketValue": 1949990,
    "cash": 1695856,
    "legend": "darkorange"
},
{
    "name": "Brokerage Account 1",
    "marketValue": 1349990,
    "cash": 1595866,
    "legend": "red"
},
{
    "name": "Brokerage Account 4",
    "marketValue": 155990,
    "cash": 160826,
    "legend": "blue"
},
{
    "name": "Brokerage Account 2",
    "marketValue": 74560,
    "cash": 19956,
    "legend": "gray"
},
{
    "name": "Account 4",
    "marketValue": 55006,
    "cash": 53006,
    "legend": "salmon"
},
{
    "name": "Account 13",
    "marketValue": 37340,
    "cash": 0,
    "legend": "green"
},
{
    "name": "Joint Account 1",
    "marketValue": 28308,
    "cash": 4167,
    "legend": "darkblue"
},
{
    "name": "Joint Account 2",
    "marketValue": 10000,
    "cash": 10000,
    "legend": "teal"
}]

Error I am receiving is "$scope.rows is undefined" Controller is not able to access $scope.rows outside success function.

Thanks :)


You need to resolve the promise in your controller, not in your factory, just return the promise:

appRoot.factory('account', ['$http', function($http) {
    return {
        info: function () {
            return $http.get('../../accountInfo.json');
        }
    }
}]);

Then in your controller do:

appRoot.controller('AccountsController', ['$scope', 'account', function($scope, account){

    account.info()
        .success(function(data) {
            $scope.rows = data;
        })
       .error(function(err) {
            return err;
        }); 

}]);

FYI, the success and error methods are deprecated:

The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.

See: https://docs.angularjs.org/api/ng/service/$http

Use the then method:

account.info().then(
    function resolved (response) {
        $scope.rows = response.data;
    },
    function rejected (response) {
        alert(response.status + ': ' + response.statusText);
    }
);

Here's a working example of the concept: http://plnkr.co/edit/UtJDpvBKKYl4rBzgXYo4?p=preview