以角度分享控制器之间的大对象

时间:2016-03-23 22:43:48

标签: javascript angularjs angularjs-directive xmlhttprequest

我正在尝试使用服务在两个控制器之间共享数据。但是在用XHR更改数据后,我没有看到数据更新。

angular    
  .module('appy', [])
  .service('MyService', function($http){
    return {
       dataToChange: {
       },
       ajaxy: function(url){
         var self = this;
         setTimeout(function(){
           console.log('now we are in the service!');
           self.dataToChange = 'something new';
           console.log(this.dataToChange);
         }, 1000);
       }
    };
  })
  .controller('c1', ['$scope', 'MyService', function($scope, MyService){
    $scope.myService = MyService;
    $scope.ajaxy = function(){
      $scope.myService.ajaxy();
    };
  }])
  .directive('dirOne', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirone-temp.html'
    };
  })
  .controller('c2', ['$scope', 'MyService', function($scope, MyService){

      $scope.myData = MyService.dataToChange;  

  }])
  .directive('dirTwo', function(){
    return {
      restrict: 'E',
      templateUrl: 'dirtwo-temp.html'
    };
  });

ajaxy进行更新时没有任何反应。我试着像this question推荐的那样设置它。没有快乐。我也试过添加手表。

$scope.$watch(function(){
  return MyService.ajaxy();
}, function(oldVal, newVal){
  $scope.somethingToChange = newVal;
  console.log($scope.somethingToChange);
});

但是没有任何事情发生。这个对象也很大。我不想$watch它。

JSBIN

1 个答案:

答案 0 :(得分:1)

当您想要像想要的那样共享数据时,您必须共享一个对象(如您给出的示例)并且永远不要替换该对象。如果你确实替换了服务中的对象,$ scope仍然会引用旧对象,这就是你的问题。

  1. 您将MyService.dataChange设置为空对象。
  2. 您将该对象注入控制器的范围
  3. 当您调用ajaxy()时,将MyService.dataChange更改为字符串' new'。此时,作用域仍保留对旧对象的引用,而不是字符串。
  4. 要解决此问题,您需要向该对象添加属性,而不是替换MyService.dataChange。绑定到共享对象的该属性时,您会注意到必须运行ajaxy()两次。要解决此问题,您需要使用角度$ timeout。

    ,而不是使用超时

    
    
    angular    
      .module('appy', [])
      .service('MyService', function($http, $timeout){
        return {
           // never replace this object, put the values you want to share as a property inside.
           sharedObject: {
             name: 'old value'
           },
           ajaxy: function(url){
             var self = this;
             // use the angular version of $timeout to make sure your scope is in sync
             $timeout(function(){
               console.log('now we are in the service!');
               self.sharedObject.name = 'new value';
               console.log(self.sharedObject);
             }, 1000);
           }
        };
      })
      .controller('c1', ['$scope', 'MyService', function($scope, MyService){
        $scope.myData = MyService.sharedObject;
        $scope.ajaxy = function(){
          MyService.ajaxy();
        };
      }])
      .directive('dirOne', function(){
        return {
          restrict: 'E',
          templateUrl: 'dirone-temp.html'
        };
      })
      .controller('c2', ['$scope', 'MyService', function($scope, MyService){ 
        $scope.myData = MyService.sharedObject;
      }])
      .directive('dirTwo', function(){
        return {
          restrict: 'E',
          templateUrl: 'dirtwo-temp.html'
        };
      });
    
    <!DOCTYPE html>
    <html>
    <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      <title>JS Bin</title>
    </head>
    <body ng-app="appy">
      
      <dir-one ng-controller="c1"></dir-one>
      <hr>
      <dir-two ng-controller="c2"></dir-two>  
      
      <script id="dirone-temp.html" type="text/ng-template">
        template one
        <button ng-click="ajaxy()">something time consuming</button>
        <div>{{myData.name}}</div>
      </script>
      
      <script id="dirtwo-temp.html" type="text/ng-template">
        template two
        <div>{{myData.name}}</div>
      </script>
    </body>
    </html>
    &#13;
    &#13;
    &#13;