0

I am new to AngularJS and I am trying to put together a practice WebApp, In the earlier versions of My App I had a single Controller and I used the $http Service to fetch Data from a JSON file like so

var App = angular.module('testApp', []);
App.controller('firstCtrl', ['$scope', '$http', function($scope, $http) {
    $scope.items = [];
    $http.get('data.json').success(function(data) {
      $scope.items = data;
    });
}]);

The $http Service worked fine, Then as I progressed I had Multiple Controllers and to Share the Data between the Controllers I moved the $http Service to a Factory like so

var App = angular.module('testApp', []);

App.factory('DataFactory', ['$http', function($http) {
    var DataFactory = {};
    var items = [];
    $http.get('data.json').success(function(data) {
      items = data;
    });
    DataFactory.data = function() {
        return items;
    };
    return DataFactory;
}]);

App.controller('firstCtrl', ['$scope', 'DataFactory',function($scope, DataFactory) {
    $scope.items = [];
    $scope.items = DataFactory.data();
}]);

And here is the HTML

<div ng-controller="firstCtrl">
  <ul>
    <li ng-repeat="item in items">{{item.name}}</li>
  </ul>
</div>

I don't know why for some reason the Data is not being Displayed after I moved the $http Service to a Factory, What am I doing wrong, I don't see any errors in the Console

4

2 回答 2

1

基于来自 cbass 的答案的简化解决方案,在控制器中展开承诺:

var App = angular.module('testApp', []);

App.factory('DataFactory', ['$http', function($http) {
    var getItems = function() {
        return $http.get('data.json');
    };

    return {
       getItems: getItems
    };
}]);

App.controller('firstCtrl', ['$scope', 'DataFactory',function($scope, DataFactory) {
   DataFactory.getItems().success(function(result){
       $scope.items = result;
   });
}]);
于 2014-07-23T20:44:10.210 回答
1

由于一个人在 18 个月内学到了很多东西,我想更新我的答案。下面的例子是我今天将如何解决这个问题。(原始解决方案见底部)

function dataFactory($http) {
    //Service interface, all properties and methods will be set to this object.
    var dataFactory={};

    //Instead of using $q, the function will just return the http-promise containing the response data.
    dataFactory.getItems=function() {
        return $http
            .get('data.json')
            .then(function(response) {
                return response.data; 
            });
    }

    //Return object containing the service interface.
    return dataFactory;
}
//Use $inject property to specifiy your DI objects, rather than using array syntax.
dataFactory.$inject=['$http'];

function firstController(DataFactory) {
    //Use this with controllerAs instead of injecting $scope.
    var vm=this;
    vm.items=[];

    DataFactory
        .getItems()
        .then(function(items) {
            vm.items=items;
        }, function(err) {
            //error handler
            alert("Got an error");
        })
}
//same here, use $inject property.
firstController.$inject=['dataFactory'];

angular
    .module('testApp', [])
    .factory('DataFactory', dataFactory)
    .controller('FirstController', firstController);

和 HTML

 <!-- Use controller as syntax -->
 <div ng-controller="firstController as first">
     <ul>
         <!-- Reference the controller by value given in controller as statement -->
         <li ng-repeat="item in first.items">{{item.name}}</li>
     </ul>
 </div>

这就是我编写代码的方式。但是,这不是我要解决的方法。我不会对数据服务进行任何更改,但我会更改控制器的实现。我要么resolve the items data通过路由器,要么将控制器和 html 捆绑为 a directive,或者从 1.5 a 开始component

使用指令

function itemsDirective() {
    function controller(DataFactory) {
        var vm=this;
        vm.items=[];

        DataFactory
            .getItems()
            .then(function(items) {
                vm.items=items;
            }, function(err) {
                //error handler
                alert("Got an error");
            })
    }
    controller.$inject=['dataFactory'];

    return {
        restrict:'E',
        template:'<div ng-controller="firstController as first">
            <ul>
                <li ng-repeat="item in first.items">{{item.name}}</li>
            </ul>
        </div>',
        controller: controller,
        controllerAs: 'first'
    }
}

angular
    .module('testApp')
    .directive('itemsDirective', itemsDirective);

旧答案(2014 年 7 月 23 日 20:26)

因为该值在返回它的值之前没有被设置。话虽如此,您可能想重组您的服务(工厂),也可以使用 $q 来处理承诺。考虑以下示例:

var App = angular.module('testApp', []);

App.factory('DataFactory', ['$http', '$q', function($http, $q) {
    var getItems = function() {
        var deffered = $q.defer();

        $http.get('data.json').success(function(data) {
             deffered.resolve(data);
        });

        return deffered.promise;
    };

    return {
       getItems: getItems
    };
}]);

App.controller('firstCtrl', ['$scope', 'DataFactory',function($scope, DataFactory) {
   $scope.items = DataFactory.getItems();
}]);

在处理诸如 http-request 之类的异步任务时使用 $q 是一种常见的做法。

于 2014-07-23T20:26:56.413 回答