0

私は AngularJS を初めて使用し、練習用の WebApp をまとめようとしています。以前のバージョンの My App では、単一のコントローラーがあり、$httpサービスを使用して JSON ファイルからデータを取得していました。

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;
    });
}]);

$httpサービスは正常に機能しました。その後、進行するにつれて、複数のコントローラーがあり、コントローラー間でデータを共有するために、$httpサービスを次のようにファクトリに移動しました

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();
}]);

そして、ここにHTMLがあります

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

$http Service をFactoryに移動した後、何らかの理由でデータが表示されない理由がわかりません。何が間違っているのでしょうか。コンソールにエラーは表示されません。

4

2 に答える 2

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);

古い回答 (14 年 7 月 23 日 20:26)

値を返す前に値が設定されないためです。Service(factory) を再構築したいかもしれませんが、$q を使用して promise を処理することもできます。次の例を検討してください。

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 に答える
1

Answer from cbass に基づく単純化されたソリューションで、コントローラーで promise をアンラップします。

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 に答える