Sharing API Data Between Controllers in AngularJS

advertisements

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


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;
    }
  }
});