我的应用程序的一部分在3个单独的页面之间共享信息。我有一个摘要"订单"实例化其子节点时实例化的控制器。孩子们是"概述","警报"和"帐户"。所以我的视图/控制器层次结构看起来像
Order
/ | \
/ | \
/ | \
/ | \
/ | \
Overview Alerts Accounts
在这3个页面的顶部,我显示了一些"订单"等级信息,如客户名称,因此我在"订单"中进行API调用。控制器,以便它可以在任何页面上使用。问题是我想保持我的所有API数据都包含在"模型中的约定"像$scope.model
这样的对象。我尝试在我的"概述"中使用angular.extend
。控制器使用" Order"中存在的$scope.model
来扩展此控制器的$scope.model
。控制器,问题是angular.extend
在返回API调用之前执行,所以我基本上只是扩展一个从未实际填充API数据的空白对象。
我的解决方案是使用Angular Events从Parent触发到Child,以便在API调用完成后扩展对象。我的代码如下所示:
订单控制器
$scope.model = new OrderModel();
API.Backups.getBackupService({ id: $stateParams.orderId }, function (data) {
$scope.model.BackupService.data = data.result;
$scope.$broadcast('parentDataReceived', $scope.model.BackupService.data);
});
概述控制器
$scope.model = new OverviewModel();
$scope.$on('parentDataReceived', function (event, data) {
angular.extend($scope.model.BackupService.data, data);
});
这很好用,但我不认为这是最好的解决方案。以前是以更优雅的方式解决了这个问题还是我的方式还好?
那么更正确的解决方案是
app.factory('OrderService', function() {
var OrderService = {};
var order = {};
OrderService.getOrder = function(id) { //send API call to get order information via OrderID }
OrderService.updateOrder = function(order) { //send API to PUT the new order information to the server }
OrderService.Current = order;
return OrderService;
});
答案 0 :(得分:0)
你正在以错误的方式解决问题。您不需要从控制器进行REST调用,然后在接收数据时将数据推送到模型(有效地将数据从控制器推送到服务)。
而是通过控制器的$ scope将您的视图绑定到服务的数据,并让数据从服务流经您的控制器的$ scope并进入您的视图。
为此,请创建订单服务,然后将Controller的$ scope(例如$ scope.model.order)上的属性分配给此Orders服务的currentOrder属性。然后,当收到数据时,只需将其分配给Orders服务中的currentOrder属性即可。
因为您的Controller的$ scope.model.order属性引用(即'绑定到')与Orders.currentOrder相同的对象,$ scope.model.order也将立即更新,视图(即HTML)
所以在你的例子中,你有类似的东西:
angular.module('OrderApp', [])
.controller('OrderCtrl', ['$scope', 'Orders', function($scope, Orders){
// $scope.model glues the values in your actual model (Orders service) to the
// view defined in your HTML template.
$scope.model = {};
// Assign $scope.model.order to OrderService.currentOrder. Because
// $scope.model.order and Orders.currentOrder both reference the same
// object, whenever Orders.currentOrder changes, $scope.model.order
// will change as well.
//
// Note that in your view, {{model.order}} will also automatically
// update.
$scope.model.order = OrderService.getCurrentOrder();
// Assume in your view you have a button wired up to getOrder()
// (e.g. ng-click=getOrder() ). Then you can display a message
// depending on whether the data has been successfully retrieved
// or not, like so:
$scope.getOrder() = function(){
// Call Orders' getOrder(). This will populate
// Orders.currentOrder; the change in currentOrder will
// instantly be reflected in $scope.model.order as they both
// reference the same object, so you don't need to worry about
// reassigning $scope.model.order to the new object referenced
// by Orders.currentOrder.
Orders.getOrder().then(function(){
$scope.infoMsg = "Order received ok";
},
function(){
$scope.errorMsg = "Error receiving order";
});
})
// OrderService acts as your model
.factory('OrderService', ['API', function(API){
var currentOrder = {};
// These are the public functions that your Controller
// (and other services) can use
var service = {
getOrder: getOrder,
getCurrentOrder: getCurrentOrder,
updateOrder: updateOrder
}
return service;
/////////////
function getOrder(){
// Return $http's promise to your Controller
return API.getBackupServiceData().then(function(data){
// When the data is retrieved, currentOrder is populated.
// The change in currentOrder will automatically be
// reflected in your Controller's $scope.model.order as
// they both reference the same object
currentOrder = data;
});
}
function getCurrentOrder(){
return currentOrder;
}
})
.factory('API', ['$http', function($http){
var service = {
getBackupServiceData: getBackupServiceData;
};
return service;
////////////
function getBackupServiceData(){
// Return $http's promise
return $http.get({ id: $stateParams.orderId }, function (data) {
// transform data if needed
return data;
},
function(response){
// handle error
}
});
}])
请注意,您经常会读到控制器应该是“粘合剂”'在你的模型和视图之间,但在Angular-land中它的含义并不总是很明显。
简单地说,您的控制器应该只包含$ scope的赋值。如果控制器中有一个包含业务逻辑的函数,或者对最终分配给$ scope的数据执行或转换的函数,请将该函数放入服务中。