Search code examples
angularjsangularjs-scopeangularjs-service

Angular - Template not refreshed with data bound from two different scopes to the same service


I bind data of two different scopes to the same common service data. When I update the data through controller 1, the data in controller 2 is not refreshed in template.

Example showing the issue :

<body ng-app="demoShareBindApp">
  <div ng-controller="FirstCtrl as first">
    Set share data to : <a href ng-click="setShareDataTo('Me')">"Me"</a>
     - <a href ng-click="setShareDataTo('Myself')">"Myself"</a>
     - <a href ng-click="setShareDataTo('I')">"and I"</a>
  </div>
  <div ng-controller="SecondCtrl as second">
    Text entered : {{sShareData}}
    <br>
    <br><a href ng-click="revealShareData()">Reveal data</a>
  </div>
  <script src="bower_components/angular/angular.js"></script>
  <script>
  angular
    .module('demoShareBindApp', [])
    .service('myService', function () {
      return {
        shareData: null
      }
    })
    .controller('FirstCtrl', ['$scope', 'myService', function ($scope, myService) {
      $scope.setShareDataTo = function(content) {
        myService.shareData = content;
      };
    }])
    .controller('SecondCtrl', ['$scope', 'myService', function ($scope, myService) {
      $scope.sShareData = myService.shareData;
      $scope.revealShareData = function() {
        console.log(myService.shareData);
      }
    }]);
  </script>
</body>

The Text entered : {{sShareData}} is never updated whereas clicking "Reveal data" shows the right share data in console.

I can't find any clue in other SO post on this particular subject. I guess it could be a matter of "$watch/$digest" but I can't figure out what is really going on here.

Any detailed explanation welcome !


Solution

  • You are sharing data through service. When data in changed under first controller, you set this updated data to service but second controller does not know that shared data referenced by service has changed, so we need to notify the second controller that data has changed or we can shared data through events

    I created a fiddle, check it

    https://jsbin.com/midebu/edit?html,js,output

    First approach. Using service

      $scope.setShareDataTo = function(content) {
        myService.shareData = content;
        $rootScope.$broadcast('datacChanged');
      };
    

    In second cntroller

    $rootScope.$on('dataChanged', function(){
        // get updated data
        $scope.sShareData = myService.shareData;
    })
    

    Other way is that, we do not need to use service , we can simply pass that shared data using events

    $scope.setShareDataTo = function(content) {
        $rootScope.$broadcast('datacChanged', content);
      };
    

    And in Second controller

     $rootScope.$on('dataChanged', function(event, data){
        // get updated data
        $scope.shareData = data;
    })