Javascript 在Angularjs中的控制器之间传递对象
我是angular的新手,正在努力理解如何使用服务将数据从一个控制器传递到另一个控制器 到目前为止,通过Angular,我已经能够理解如何在HTML中调用控制器并将数据传递给它们。为了设置一个Map控制器,这一点特别好,我可以查看来自PHP的结果列表,并将这些结果中的数据发送到我的控制器,以便在地图上创建标记 让我完全困惑的是,有一个控制器通过ElasticSearch调用生成嵌套对象,然后将数据传递给我的地图控制器Javascript 在Angularjs中的控制器之间传递对象,javascript,angularjs,angular-controller,Javascript,Angularjs,Angular Controller,我是angular的新手,正在努力理解如何使用服务将数据从一个控制器传递到另一个控制器 到目前为止,通过Angular,我已经能够理解如何在HTML中调用控制器并将数据传递给它们。为了设置一个Map控制器,这一点特别好,我可以查看来自PHP的结果列表,并将这些结果中的数据发送到我的控制器,以便在地图上创建标记 让我完全困惑的是,有一个控制器通过ElasticSearch调用生成嵌套对象,然后将数据传递给我的地图控制器 <div ng-controller="IndexController"
<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>
最初,我尝试通过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>
IndexController.js
App.factory("resultsService", function() {
var loadListingsArea = {};
return {
getLocations: function() {
return loadListingsArea
},
setLocations: function(loc) {
loadListingsArea = loc;
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(只是在这个阶段尝试转储对象,不包括我为谷歌地图编写的很长的代码库)
这是从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.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;
});
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;
});
而只需要得到它的控制器可以做到:
resultsService.loadLocations() // returns a promise
.then(function(data){
$scope.listingsArea = data;
});
resultsService.getLocations()
.then(function(data){
$scope.listingsArea = data;
});
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;
});
这可能需要一些额外的按摩,但它应该给你一个方向,头部
还请注意,以这种方式共享对象意味着您可以从任一控制器编辑相同的对象。要避免这种情况,请传递数据对象的angular.copy。该
$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(data){
$scope.listingsArea = data;
});
resultsService.getLocations()
.then(function(data){
$scope.listingsArea = data;
});
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;
});
而只需要得到它的控制器可以做到:
resultsService.loadLocations() // returns a promise
.then(function(data){
$scope.listingsArea = data;
});
resultsService.getLocations()
.then(function(data){
$scope.listingsArea = data;
});
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;
});
请注意,两个控制器都需要检查错误
还要注意,。然后
返回的数据与。success
不同
AngularJS团队已经清醒过来,不赞成.success
。我们都应该使用。然后从现在开始使用
有关.success
的弃用信息和更多信息,请参阅最新的使用服务共享,或使用$broadcast直接发送。我知道,我不知道广播。所以你可以直接在一个控制器中启动它,发送给另一个控制器?嗯,在这个过程中有些东西被破坏了,因为根据你的建议,mapcontroller永远不会完全加载,因此不会执行。问题似乎出在indexcontroller中,因为注释那里的代码可以确保它的执行。如果发现这个问题,必须在函数中定义$http和$window。但仍然无法100%确定是否正在共享完整对象。我在我的应用程序中执行类似操作。我有错误回调,我没有将数据放在$scope上,因为我使用了“controller as”语法,这是我能想到的唯一区别。这应该以你需要的方式来分享这个对象。这很公平。经过进一步检查,我能够确认服务正在检索该对象,该对象正在传递给indexController,但它没有传递给mapController。此时,getLocations总是返回null。请尝试将listingArea变量放在self上的服务中,请参阅我的编辑。如果这不起作用,那可能是一种竞赛条件。您是同时实例化两个控制器,还是一个替换另一个(就像您使用ngView一样)?如果在返回任何数据之前调用load,然后调用get,则第二个控制器将返回null。为了解决这个问题,您可以将数据放在包装器对象中,并存储/共享包装器对象。这样,一旦返回数据并将其放入包装器对象,它将更新controllersTested和works。从它的运行方式来看,从我对脚本的这些元素的阅读来看,在转到下一部分之前,请等待不同部分的运行。如果在loadLocations之前调用getLocations,并调用它,则getLocations将返回一个空对象。然后,调用它将失败。因此,当第二个控制器包含但第一个控制器不包含时,这将失败。无论哪种方式,Mine都会返回一个承诺。then不会失败,但如果从未调用loadLocations,也不会得到解决。@mgiesa Look-at不完全适用,因为这里额外要求从另一个控制器访问数据。要增加安全性,您必须在getLocations中检查self.listingPromise实际上是一个承诺,如果不是,您必须做出一个承诺才能返回。您可以将该方法更改为lazy-load,因此,如果承诺还不存在,您可以调用load函数并获得承诺。或者从两个控制器调用load方法,如果承诺已经存在,则返回它,而不是发出新的请求。但实际上,您的代码将导致未处理的错误。这仍然会返回空对象,因为空对象是真实的。尝试执行typeof,例如if(self.listingPromise&&typeof self.listingPromise.then==='function')返回self.listingPromise。或者用null而不是{}初始化listingPromise