基本上我的应用程序的核心在于通过$ http请求从服务器检索的一组数据。一旦数据可供客户端使用(作为对象数组),我需要它用于多个视图,并且希望在它们之间保持它的状态,例如,如果它已被过滤,我希望只有过滤后的数据可用于其他观点。
目前我有一个检索数据的基本服务,然后在app范围的控制器中管理数据(数组)的状态(见下文)。这很好用,但是当我尝试在每个视图的控制器上维护数组长度,过滤状态,可见/隐藏对象时,它开始变得一团糟,因为我必须在应用程序范围的控制器中保持currentVenue等的跟踪。注意:我在每个视图中使用ng-repeat来显示和过滤数据(另一个原因我想让它在中心点过滤)。
显然这不是最佳选择。我假设我应该使用服务来维护场地对象的数组,因此它将包含当前场所,当前页面,负责过滤阵列等,并将其注入每个控制器。我的问题是,如何设置服务以具有此功能(包括在启动时从服务器加载数据;这将是一个良好的开端tbh),这样我就可以实现这一点,然后将结果绑定到范围。即:每个视图控制器中的$scope.venues = venues.getVenues
和$scope.current = venues.currentVenue
。
services.factory('venues', function ($http, $q) {
var getVenues = function() {
var delay = $q.defer();
$http.get('/api/venues', {
cache: true
}).success(function (venues) {
delay.resolve(venues);
});
return delay.promise;
}
return {
getVenues: getVenues
}
});
controllers.controller('AppCtrl', function (venues, $scope) {
$scope.venuesPerPage = 3;
venues.getVenues().then(function (venues) {
$scope.venues = venues;
$scope.numVenues = $scope.venues.length;
$scope.currentPage = 0;
$scope.currentVenue = 0;
$scope.numPages = Math.ceil($scope.numVenues / $scope.venuesPerPage) - 1;
}
});
很抱歉长篇大论,不知道如何准确指定。提前谢谢。
答案 0 :(得分:3)
策略是利用对象引用。如果将共享数据移动到对象,然后将该对象设置为$scope
,则$ scope的任何更改都会直接更改服务对象,因为它们是相同的($scope
引用该服务)。
Here's a live sample demonstrating this technique (click).
<div ng-controller="controller-one">
<h3>Controller One</h3>
<input type="text" ng-model="serv.foo">
<input type="text" ng-model="serv.bar">
</div>
<div ng-controller="controller-two">
<h3>Controller Two</h3>
<input type="text" ng-model="serv.foo">
<input type="text" ng-model="serv.bar">
</div>
JS:
var app = angular.module('myApp', []);
app.factory('myService', function() {
var myService = {
foo: 'abc',
bar: '123'
};
return myService;
});
app.controller('controller-one', function($scope, myService) {
$scope.serv = myService;
});
app.controller('controller-two', function($scope, myService) {
$scope.serv = myService;
});
答案 1 :(得分:2)
我把这个快速地放在一起作为起点。您可以以任何方式重组工厂。一般的想法是,范围内的所有数据现在都已移至工厂服务中的对象。
不是仅使用响应数组解析$http
,而是使用包含服务器阵列的更大对象来解析它。由于所有数据现在都在一个对象中,因此可以从任何控制器更新
services.factory('venues', function ($http, $q) {
var getVenues = function(callback) {
var delay = $q.defer();
$http.get('/api/venues', {
cache: true
}).then(function (response) {
/* update data object*/
venueData.venues=response.data;
venueData.processVenueData();
/* resolve with data object*/
delay.resolve(venueData);
}).then(callback);
return delay.promise;
}
var processVenueData=function(){
/* do some data manipulation here*/
venueData.updateNumPages();
}
var venueData={
venuesPerPage : 3,
numVenues:null,
currentVenue:0,
numPages:null,
venues:[],
updateNumPages:function(){
venueData.numPages = Math.ceil(venueData.numVenues / venueData.venuesPerPage) - 1;
},
/* create some common methods used by all controllers*/
addVenue: function( newVenue){
venueData.venues.push( newVenue)
}
}
return {
getVenues: getVenues
}
});
controllers.controller('AppCtrl', function (venues, $scope) {
venues.getVenues(function (venueData) {
/* now have much bigger object instead of multiple variables in each controller*/
$scope.venueData=venueData;
})
});
现在标记参考venueData.venues
或venueData.numPages
通过跨控制器共享方法,您现在只需将带有ng-model
的表单对象绑定到具有ng-click="venueData.addVenue( formModel)"
(或使用ng-submit
)的按钮,您就可以添加新的地点来自任何控制器/指令而无需向控制器添加一些代码