2017-03-09 6 views
0

2つのコントローラーと2つのサービスで、3秒ごとに1つのサービスが呼び出されるという単純な例を作成しようとしています。setInterval操作で値をバインドできません

コントローラ1は、コントローラ2で使用される値を変更するサービスを呼び出します。私は値を別のサービスに渡しますが、値が私の例の「停止」ボタンを押した後でしかHTMLページで更新されません。

投票ごとにページの値を更新できますか?

<html ng-app="myApp"> 
<head> 
    <title>MyApp</title> 
    <script src="angular.js"></script> 
    <script> 
     var app = angular.module('myApp',[]); 


     app.service('SimpleService', function() { 

      var _value = 0; 

      var setValue = function(v) { 
       _value = v; 
      } 

      var getValue = function(){ 
       return _value; 
      } 

      return { 
      setValue: setValue, 
      getValue: getValue 
      }; 
     }) 

     app.service('PollService', function(SimpleService) { 

      var poll = undefined; 


      var startPolling = function(){ 

       poll = setInterval(function(){ 
        console.info('poll...'); 
        console.info(SimpleService.getValue()); 
        SimpleService.setValue(SimpleService.getValue()+1); 

       }, 3000); 

      } 

      var stopPolling = function(){ 
       clearInterval(poll); 
      } 


      return { 
      startPolling: startPolling, 
      stopPolling: stopPolling 
      }; 
     }) 


     app.controller('Controller1',function($scope, PollService){ 
      var poll = undefined; 


      $scope.startPolling = function(){ 
       PollService.startPolling(); 
      } 

      $scope.stopPolling = function(){ 
       console.info('stop'); 
       PollService.stopPolling(); 
      } 

     }); 


     app.controller('Controller2', function($scope, SimpleService){ 
      $scope.newVal = function(){ 
       return SimpleService.getValue(); 
      }    
     }); 
    </script> 

</head> 

<body> 
    <div ng-controller="Controller1"> 
     <button ng-click="startPolling()">Start</button> 
     <button ng-click="stopPolling()">Stop</button> 
     <br/> 
     <br/> 

    </div> 
    <div ng-controller="Controller2"> 
      <h5>New value: {{newVal()}}</h5> 
     </div> 

</body> 

よろしく。

+2

https://docs.angularjs.org/api/ng/service/$interval – sh0ber

+2

[この質問]と同じ原則(http:// stackoverflow。com/questions/42701048/how-to-pass-vm-to-a-settimout-in-angularjs)がここに適用されます。この場合、[$ interval](docs.angularjs.org/api/ng/service/$interval)を@ sh0berと表記して – lealceldeiro

+0

PollService.stopPolling()のコードはどこですか? –

答えて

1

のsetIntervalは角関数ではないので、角度の値が更新されていることを知りません。その値がダーティであることをDOMに伝えることはできないため、更新されません。あなたがsetInterval代わりの角の$間隔を継続して使用する場合は

、あなたのポーリングサービスへ$rootScopeを注入することができ、その後、あなたはDOMを更新する値を消化するために$rootScope.$applyを使用することができます。あなたはあなたのsetInterval機能内に

$rootScope.$apply(function(){ 
    SimpleService.setValue(SimpleService.getValue()+1); 
}); 

の機能を使用することができます。

それ以外の場合、$intervalは、setInterval関数のangular.jsラッパーであり、手動で$ applyを呼び出す必要はありません。

コードに変更を加え、コントローラスコープでのサービスの使用をより適切に構造化する方法の例をいくつか示しました。

See here for updated code

サービスが目的であるので、主に、我々は、直接ではなく、参照の個々のオブジェクトのキーよりも、コントローラスコープにサービス自体を追加することによって、DOM内のサービスのコンテキストを参照することができます。これにより、{{newValue()}}を呼び出すときと同じように、DOMからゲッター関数を呼び出す必要がなくなります。

3

SimpleServiceでセッターを呼び出すたびにダイジェストサイクルを呼び出す必要があります。新鮮なダイジェスト・サイクルが開始されない限り、ビュー・バインディングは更新されません。ここに作業コードスニペットがあります。

app.service('SimpleService', function($rootScope) { 

     var _value = 0; 

     var setValue = function(v) { 
      _value = v; 
      $rootScope.$apply(); //added this here 
     } 

     var getValue = function(){ 
      return _value; 
     } 

     return { 
     setValue: setValue, 
     getValue: getValue 
     }; 
    }) 

scope.apply()を実行する必要があります。 $ applyはテンプレート内の式を評価し、新しいダイジェストサイクルを開始します。$ digestフェーズでは、スコープはすべての$ watch式を調べ、前の値と比較します。あなたはそれについてのドキュメントをチェックアウトすることができますhere

私はあなたのコードに気づいた他のいくつかの問題:

ここ
app.controller('Controller2', function($scope, SimpleService2){ 
    $scope.newVal = function(){ 
    return SimpleService.getValue(); 
    }    
}); 

、SimpleServiceでに名前を修正します。

stopPropagation.Iための方法は、次のようにあなたのコードの作業を取得するためにPollServiceにこれを追加しましたありません:

var stopPolling = function(){ 
    clearInterval(poll); 
} 
関連する問題