Обмен наблюдаемым массивом ссылок между контроллерами в 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;
}

Надеюсь, это сработает для вас!