Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing observable array reference between controllers in AngularJS

Tags:

angularjs

I am writing an AngularJS application in which one array (a list of active work orders) is used in many different controllers. This array is refreshed periodically using an $http call to the server. In order to share this information I've placed the array in a service.

The array in the service starts out empty (or, for debugging purposes, with dummy values ["A", "B", "C"]) and then queries the server to initialize the list. Unfortunately, all my controllers seem to be bound to the pre-queried version of the array -- in my application all I see are the dummy values I initialized the array with.

My goal is to bind the array into my controllers in such a way that Angular will realize that the array has been updated and cause my view to re-render when the array changes without my having to introduce a $watch or force my $http call to wait for results.

Question: How do I bind the wo_list array from my service to my controller so that Angular treats it like a regular observable part of the model?

I have:

  1. A service that contains the array and a refresh function used to initialize and periodically update the array from the server (I know this is working by the console.log() message). For debugging purposes I'm initializing the array with the placeholders "A", "B", and "C" -- the real work orders are five digit strings.

    angular.module('activeplant', []).
       service('workOrderService', function($http) {
    
       wo_list = ["A", "B", "C"]; //Dummy data, but this is what's 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();
           }
    
       }
     })
    
  2. A controller that should bind to the array in workOrderService so that I can show a list of work orders. I'm binding both the service and the array returned by the service in two different attempts to get this to work.

    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()
    
    }
    
  3. A view template that iterates over the bound array in the plant controller to print a list of work orders. I'm making two attempts to get this to work, the final version will only have the ul element once.

    <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>
    
  4. Several other view / controller pairs, not shown here, that also bind and iterate over the array of work orders.

like image 218
Larry Lustig Avatar asked Jan 15 '13 15:01

Larry Lustig


People also ask

How can we share the data between controllers in AngularJS?

Approach: To share data between the controllers in AngularJS we have two main cases: Share data between parent and child: Here, the sharing of data can be done simply by using controller inheritance as the scope of a child controller inherits from the scope of the parent controller.

Is used to share data between controller and view in AngularJS?

14) Which of the following is used to share data between controller and view in AngularJS? Answer: B: "using services" is the correct answer.

How do you pass variables between components in AngularJS?

Inside the . component in the model that you just passed data into (ModelOne), use the same name as you declared in the HTML ('data') and add it into a bindings object (note: bindings, plural). You can use '<', '=', '&' or '@' depending on what you need. And then repeat step 2 and 3 for the next child component.

Who is known as father of AngularJS?

AngularJS was originally developed in 2009 by Miško Hevery at Brat Tech LLC as the software behind an online JSON storage service, that would have been priced by the megabyte, for easy-to-make applications for the enterprise.


2 Answers

See if this solves your problem:

Instead of wo_list = data, populate the same array. When you assign a new data array to wo_list, you lose the bindings to the old array -- i.e., your controllers are probably still bound to the previous data array.

wo_list.length = 0
for(var i = 0; i < data.length; i++){
    wo_list.push(data[i]);
}

See https://stackoverflow.com/a/12287364/215945 for more info.

Update: angular.copy() can/should be used instead:

angular.copy(data, wo_list);

When a destination is supplied to the copy() method, it will first delete destination's elements, and then copy in the new ones from source.

like image 84
Mark Rajcok Avatar answered Jan 01 '23 23:01

Mark Rajcok


You can put the array which all the controllers use in a parent controller. Since scopes inherit from higher scopes, this'll mean that all the controllers have the same copy of the array. Since the array is a model of the higher scope, changing it will update the view, whenever it's used.

Example:

<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>

You only need to define the wonums array in the MainController:

function MainControllerWithYourArray($scope, workOrderService){
    $scope.wonums = workOrderService.wonums;
}

Hope this works for you!

like image 28
yoxigen Avatar answered Jan 01 '23 23:01

yoxigen