Обмен наблюдаемым массивом ссылок между контроллерами в AngularJS
Я пишу приложение AngularJS, в котором один массив (список активных заказов на работу) используется во многих разных контроллерах. Этот массив обновляется периодически, используя вызов $http
на сервер. Чтобы поделиться этой информацией, я поместил массив в службу.
Массив службы запускается пустым (или для целей отладки с фиктивными значениями ["A", "B", "C"]
), а затем запрашивает сервер для инициализации списка. К сожалению, все мои контроллеры, похоже, связаны с предварительно запрошенной версией массива - в моем приложении все, что я вижу, - это фиктивные значения, которые я инициализировал массивом с помощью.
Моя цель - связать массив с моими контроллерами таким образом, чтобы Angular понял, что массив обновлен и заставляет мое представление повторно отображать, когда массив изменяется без моего представления $watch
или заставить мой вызов $http
ждать результатов.
Вопрос: Как связать массив wo_list с моей службой с моим контроллером, чтобы Angular рассматривал его как обычную наблюдаемую часть модели?
У меня есть:
-
Служба, содержащая массив и функцию обновления, используемые для инициализации и периодического обновления массива с сервера (я знаю, что это работает с сообщением console.log()
). Для целей отладки я инициализирую массив с помощью заполнителей "A", "B" и "C" - настоящие порядки работы представляют собой пятизначные строки.
angular.module('activeplant', []).
service('workOrderService', function($http) {
wo_list = ["A", "B", "C"]; //Dummy data, but this is what bound in the controllers.
refreshList = function() {
$http.get('work_orders').success(function(data) {
wo_list = data;
console.log(wo_list) // shows wo_list correctly populated.
})
}
refreshList();
return {
wonums: wo_list, // I want to return an observable array here.
refresh: function() {
refreshList();
}
}
})
-
Контроллер, который должен привязываться к массиву в workOrderService, чтобы я мог отображать список рабочих заказов. Я связываю как службу, так и массив, возвращаемые службой, в двух разных попытках заставить это работать.
function PlantCtrl($scope, $http, workOrderService) {
$scope.depts = []
$scope.lastUpdate = null
$scope.workorders = workOrderService
$scope.wonums = workOrderService.wonums // I want this to be observable
$scope.refresh = function() {
$scope.workorders.refresh()
$http.get('plant_status').success(function(data) {
$scope.depts = data;
$scope.lastUpdate = new Date()
});
}
$scope.refresh()
}
-
Шаблон представления, который выполняет итерацию над связанным массивом в контроллере завода, чтобы распечатать список рабочих заказов. Я делаю две попытки заставить это работать, окончательная версия будет иметь только элемент ul.
<div ng-controller="PlantCtrl">
<div style='float:left;background-color:red' width="20%">
<h2>Work Orders</h2>
<ul>
<li ng-repeat="wonum in workorders.wonums"><a href=""> {{wonum}} </a></li>
</ul>
<ul>
<li ng-repeat="wonum in wonums"><a href=""> {{wonum}} </a></li>
</ul>
</div>
</div>
-
Несколько других пар представлений/контроллеров, не указанных здесь, которые также связывают и перебирают по массиву рабочих заказов.
Ответы
Ответ 1
Посмотрите, решит ли это вашу проблему:
Вместо wo_list = data
введите один и тот же массив. Когда вы назначаете новый массив data
в wo_list, вы теряете привязки к старому массиву - т.е. Ваши контроллеры, вероятно, все еще привязаны к предыдущему массиву data
.
wo_list.length = 0
for(var i = 0; i < data.length; i++){
wo_list.push(data[i]);
}
Подробнее см. fooobar.com/questions/181517/....
Обновление: angular.copy() можно/следует использовать вместо:
angular.copy(data, wo_list);
Когда пункт назначения передается методу copy(), он сначала удаляет целевые элементы, а затем копирует их из источника.
Ответ 2
Вы можете поместить массив, который все контроллеры используют в родительском контроллере. Поскольку scopes наследуются от более высоких областей, это будет означать, что все контроллеры имеют одну и ту же копию массива. Поскольку массив является моделью с более высокой областью действия, ее изменение будет обновлять представление, когда оно будет использоваться.
Пример:
<div ng-controller="MainControllerWithYourArray">
<div ng-controller="PlantCtrl">
Wonums length: {{wonums.length}}
</div>
<div ng-controller="SecondCtrl">
Wonums length in other controller: {{wonums.length}}
</div>
</div>
Вам нужно только определить массив выигрышей в MainController:
function MainControllerWithYourArray($scope, workOrderService){
$scope.wonums = workOrderService.wonums;
}
Надеюсь, это сработает для вас!