1

我是 Angular 的新手,正在努力了解如何使用服务将数据从一个控制器传递到另一个控制器。

到目前为止,使用 Angular,我已经能够理解如何调用控制器并将数据从 HTML 中传递给它们。为了设置地图控制器,这特别好,我查看来自 PHP 的结果列表,并将这些结果中的数据发送到我的控制器,以在地图上创建标记。

让我完全困惑的是,有一个控制器通过 ElasticSearch 调用生成嵌套对象,然后将该数据传递给我的地图控制器。

最初我尝试通过 ng-repeat 循环遍历结果,虽然我能够输出结果,但我的 MapController 无法读取 HTML 中的这些结果,因为它们在我的 IndexController 的范围内(输出数据)。好吧,我认为情况就是这样。

这是我尝试过的,虽然它输出了数据,但我永远无法在 MapController 中读取它。

<div ng-controller="IndexController">
    <div ng-repeat="r in listingsArea.results">
        <div class="component home-listings"
            data-id="{{r.id}}"
            data-url="{{r.url}}"
            data-lat="{{r.lat}}"
            data-lng="{{r.lon}}"
            data-address="{{r.address}}"
            data-price="{{r.price}}"
        ></div>
    </div>
</div>

我读过将数据从一个控制器传递到另一个控制器的最佳方式是通过服务。我在这里关注了很多文档,但尽管如此,我显然遗漏了一些东西,因为它不起作用。

这是我迄今为止所拥有的:

结果服务.js

App.factory("resultsService", function() {

var loadListingsArea = {};

return {
    getLocations: function() {
        return loadListingsArea
    },

    setLocations: function(loc) {
        loadListingsArea = loc;

索引控制器.js

App.controller('IndexController', function($scope, resultsService) {

$scope.listingsArea = [];

$scope.loadListingsArea = function() {
    $http.get($window.location + '/listingsarea')
        .success(function(data) {
            $scope.listingsArea = data;
        }
    );
}

$scope.$watch(function() {
    return $scope.loadListingsArea;
}, function() {
    resultsService.setLocations($scope.loadListingsArea);
});
});

MapController.js(只是想在这个阶段转储对象,不包括我很长的谷歌地图代码库)

App.controller('MapController', function($scope, resultsService) {

$scope.locations = resultsService.getLocations();

alert($scope.locations);

这是我的对象从 indexcontroller.js 转储时的示例

{"count":4,
"results":[
      {"id":"1153292",
       "url":"/this-is-my-slug/1153292",
       "lat":"-37.822034",
       "lon":"144.969553",
       "address":"1302/430 Place Road",
       "price":"$2,350,000",
       "hero":"some-image-here.jpg"}
]};
4

2 回答 2

1

$http服务返回一个承诺。存储那个。没必要做这些事$q.defer

App.factory("resultsService", function() {

  var self = this;
  self.listingsPromise = undefined;

  return {
      loadLocations: function(url) {
           self.listingPromise = $http.get(url);
           return self.listingPromise;
      },
      getLocations: function() {
        return self.listingPromise;
      }
  );
}

启动检索的控制器可以这样做:

resultsService.loadLocations() // returns a promise
  .then(function(response){
    $scope.listingsArea = response.data;
  }) .catch ( function (error) {
    throw error;
  });

而只需要获取它的控制器可以这样做:

resultsService.getLocations()
  .then(function(response){
    $scope.listingsArea = response.data;
  }) .catch ( function(error) {
    throw error;
  });

请注意,两个控制器都需要检查错误。

另请注意,.then返回的数据不同于.success.

AngularJS 团队已经意识到并弃用了.success. 我们都应该.then从现在开始使用。

有关弃用的.success信息和更多信息,请参阅最新的AngularJS $http API Docs

于 2015-11-21T05:42:33.100 回答
0

将 $http.get 移动到服务中的函数中。编辑为使用 $q.deferred 而不是返回 $http 的承诺。

App.factory("resultsService", function() {

  var self = this;
  self.deferred = $q.defer();
  self.listingsArea = {};

  return {
      loadLocations: function() {
          $http.get($window.location + '/listingsarea')
              .then(function(data){
                 self.listingsArea = data;
                 self.deferred.resolve(self.listingsArea);
              },
              function(e){
                self.deferred.reject(e);
              });
          return self.deferred.promise;
      },
      getLocations: function() {
        return self.deferred.promise;
      }
  );
}

启动检索的控制器可以这样做:

resultsService.loadLocations() // returns a promise
  .then(function(data){
    $scope.listingsArea = data;
  });

而只需要获取它的控制器可以这样做:

resultsService.getLocations()
  .then(function(data){
    $scope.listingsArea = data;
  });

这可能需要一些额外的按摩,但它应该给你一个前进的方向。

另请注意,以这种方式共享对象意味着您可以从任一控制器编辑相同的对象。为避免这种情况,请改为传递数据对象的 angular.copy。

于 2015-11-21T02:15:45.713 回答