0

I have a parent controller with some children controllers, and I want them all to share the same data that I retrieve from an Api service.

Controllers:

var app = angular.module('mymodule',[]);

app.controller('main', ['$scope', 'Api', function($scope, Api) {
    var getList1 = Api.getList1()
      .then(function(resp) {
        $scope.list1 = resp.data;
      });

    var getList2 = Api.getList2()
      .then(function(resp) {
        $scope.list2 = resp.data;
      });
}]);

app.controller('child1', ['$scope', function($scope) {
    $scope.list1 = ?
    $scope.list2 = ?
}]);

app.controller('child2', ['$scope', function($scope) {
    $scope.list1 = ?
}]);

View:

<div ng-controller="main">
    <ul>
        <li ng-repeat="list in list1">
            {{list.item}}
        </li>
    </ul>
    <div ng-controller="child1">
        <ul>
            <li ng-repeat="list in list1">
                {{list.item}}
            </li>
        </ul>
        <ul>
            <li ng-repeat="list in list2">
                {{list.item}}
            </li>
        </ul>
    </div>
    <div ng-controller="child1">
        <ul>
            <li ng-repeat="list in list1">
                {{list.item}}
            </li>
        </ul>
    </div>
</div>

I tried to use this solution with Angular’s events mechanism ($on, $emit).
The problem was that I had to figure out which child controller is active and send the data when the promise has resolved. It ends with ugly spaghetti code...

Community
  • 1
  • 1
Liad Idan
  • 556
  • 1
  • 7
  • 17
  • 4
    Possible duplicate of [Share data between AngularJS controllers](http://stackoverflow.com/questions/21919962/share-data-between-angularjs-controllers) – Slava.K Feb 20 '17 at 15:39
  • 2
    @Mistalis Yes, he has an `Api` service to make requests to server, nothing prevents from creating another service that will be responsible for storing and sharing received data between controllers. Anyways, IMO a universal way to share data in angular is via the service – Slava.K Feb 20 '17 at 15:48

3 Answers3

2

Well, the best way is to use a service to have your API handling atomar placed inside your application. This fiddle shows you how you could achieve what you try to. By using AngularJS services you will be able to share the same data, objects and functions between controllers and let them interact with eachother. This is undepending on the amount of your controllers inside your application.

The following example is a full working API service with real HTTP-Requests and a real AngularJS service handling. It will help you by implement such logic inside your application. Please dont forget to check out the fiddle demo.

View

<div ng-controller="MyCtrl">
   <h1>
    MyCtrl
   </h1>
   <button ng-click="clearData()">
    Clear data by using MyCtrl
   </button>
   <div ng-repeat="user in users">
     <p>
       Username: {{ user.name }}
     </p>
   </div>
</div>
<br /><br />
<div ng-controller="MyOtherCtrl">
 <h1>
  MyOtherController
 </h1>
   <button ng-click="clearData()">
    Clear data by using MyOtherController
   </button>
   <div ng-repeat="user in users">
     <p>
       Username: {{ user.name }}
     </p>
   </div>
</div>

AngularJS Application

var myApp = angular.module('myApp',[]);;


myApp.controller('MyCtrl', function ($scope, apiService) {
   $scope.users = apiService.getResponseData();
   $scope.$watch(function () { return apiService.getResponseData()}, function (newValue, oldValue) {
     $scope.users = newValue
   });

   $scope.clearData = function () {
        apiService.reset();
   }
});
myApp.controller('MyOtherCtrl', function ($scope, apiService) {

   apiService.loadData();

   $scope.$watch(function () { return apiService.getResponseData()}, function (newValue, oldValue) {
     $scope.users = newValue
   });

   $scope.clearData = function () {
        apiService.reset();
   }
})


myApp.service('apiService', function ($http) {

  var responseData = null;

  return {
    loadData: function () {
      return $http({
         url: 'https://jsonplaceholder.typicode.com/users',
         method: 'GET'
      }).then(function (response) {
         responseData = response.data
      });
    },
    getResponseData: function () {
       return responseData
    },
    reset: function () {
       responseData = null;
    }
  }
});
lin
  • 17,956
  • 4
  • 59
  • 83
0

As your data is in the scope of the parent controller, you can access it in children controllers with $scope.$parent:

app.controller('child1', ['$scope', function($scope) {
    $scope.list1 = $scope.$parent.list1;
    $scope.list2 = $scope.$parent.list2;
}]);
Mistalis
  • 17,793
  • 13
  • 73
  • 97
  • A better approach is to use factories instead of DOM hierarchy controller binding. – lin Feb 20 '17 at 15:43
  • @lin 100% agreed, but *as I understand* the question, it is about accessing data in children controllers. – Mistalis Feb 20 '17 at 15:44
  • @Mistalis Maybe my question is not so clear but I want to be able to access the same data form every controller, I tried to write a service but all I got in the controller was undefined values. – Liad Idan Feb 20 '17 at 15:58
0

Write your children as directives, and then you can inject data on the scope.

yourModule.directive('child1', function() {
    return {
       scope: {list1:'=',
       controller: function (scope) {
           //not sure you even need a controller, but it might look like this
           scope.doSomething =  function() {
              //access scope.list1 here
           }
       },
       template: '<ul><li ng-repeat="list in list1">{{list.item}}<li><ul>'
    }
}

Usage:

<child1 list1="list1"></child1>
Amy Blankenship
  • 6,485
  • 2
  • 22
  • 45