在Angularjs中的控制器之间传递对象

Passing object between controllers in Angularjs

本文关键字:对象 之间 控制器 Angularjs      更新时间:2023-09-26

我是angular的新手,很难理解如何使用服务将数据从一个控制器传递到另一个控制器。

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

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

最初,我尝试通过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>

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

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

ResultsService.js

App.factory("resultsService", function() {
var loadListingsArea = {};
return {
    getLocations: function() {
        return loadListingsArea
    },
    setLocations: function(loc) {
        loadListingsArea = loc;

IndexController.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"}
]};

$http服务返回一个promise。把它储存起来。不需要做$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

将$http.get移动到服务中的一个函数中。已编辑为使用$q.redeferred,而不是返回$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.副本。