2016-03-23 21 views
1

サービスを使用して2つのコントローラ間でデータを共有しようとしています。しかし、私は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

+2

まず第一にちょうどFYI、 'setTimeout'で、あなたの' this'はwindow' 'を参照しています。 'setTimeout'コールバックをオブジェクトにバインドする必要があります(しかし、これはあなたの主な問題を解決しません)。 –

+1

素晴らしい点。私はこれを嘲笑していたときにそれを考えなかった。ありがとう! – 1252748

+0

私はそのコントローラのデータを取得してc1とc2の間で共有できるように、ルートコントローラを使用することをお勧めします。 – sniels

答えて

1

あなたがやろうとしているようなあなたのデータを共有したいときに、あなたは(あなたが与えたので、例のような)オブジェクトを共有し、決してそのオブジェクトを交換する必要があります。サービス内のオブジェクトを置き換えると、$ scopeは引き続き古いオブジェクトを参照しますが、これはあなたの問題です。

  1. MyService.dataChangeを空のオブジェクトに設定します。
  2. コントローラのスコープにオブジェクトを挿入します。
  3. ajaxy()を呼び出すと、MyService.dataChangeが文字列「something new」に変更されます。この時点で、スコープには古いオブジェクトへの参照が保持され、文字列への参照は保持されません。

これを解決するには、MyService.dataChangeを置き換える代わりに、そのオブジェクトにプロパティを追加する必要があります。共有オブジェクトのそのプロパティにバインドすると、ajaxy()を2回実行する必要があることがわかります。これを解決するには、timeoutを使用する代わりに、angle $ 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>

+0

@thomas、私はrootcontrollerとスコープを共有しませんでした。なぜなら、この戦略はよりきれいに見えるからです。 – sniels

+0

ありがとう!残念ながら私がいるところでは遅れており、朝にこれをチェックしなければならないでしょう。 'ajaxy'が' $ http() '' get'であれば、これはどのように変化しますか? – 1252748

+0

$ timeoutを '$ http.get(url).then( 関数の成功(レスポンス){self.sharedObject.data = response.data;}、 ファンクションエラー(レスポンス){...} ) ; – sniels

関連する問題