簡體   English   中英

AngularJS數據綁定-監視周期未觸發

[英]AngularJS Data Binding - Watch cycle not triggering

假設以下JSFiddle: https ://jsfiddle.net/pmgq00fm/1/

我希望基於第39行上的setInterval()來實時更新NVD3圖表,該setInterval()更新指令所綁定的數據。 以下是有關體系結構和代碼的快速指導:

  • 該指令在ThisController的范圍內
  • 使用指令中的'='雙向綁定數據
  • 只要指令在$ watch周期內檢測到數據更改,就應該在圖表上調用更新函數。
  • $ watch是一個很深的手表,因此應該檢測值的變化
  • 在指令中設置了一個間隔,以在控制台中打印值的更改。 每當調用updateFnc時,控制器都會打印更新后的數組。
  • 由於某些原因,指令中的數據值永遠不會與控制器中的數據匹配。
  • 在控制器和指令中都可以修改這些值。
  • 指令中的$ watch僅在執行時調用
  • 該代碼基於本教程,並遵循其中說明的數據綁定所必需的所有步驟。

要調試,請運行JSFiddle並打開控制台以查看對象和調試打印。

HTML:

<div id="stats-container" ng-app="myApp" ng-controller="ThisController">
    <div id="nvd3-test" nvd3-discrete-bar data="data.graph">       
</div> 

JS:

myControllers.controller('ThisController', ['$scope', function ThisController($scope){
      $scope.data = { graph : [ ... ] };

      updateFnc = function(data){
        for(var i = 0; i < data[0].values.length ; i++){
          data[0].values[i].value = Math.random();
        }
        console.log(Date.now()/1000 + ": In Controller");
        console.log(data);
      };

      setInterval(function(){
        updateFnc($scope.data.graph);
      }, 1000);
 }]);

myServices.factory('NVD3Wrapper', ['NVD3S', 'D3S', '$q', '$rootScope', function NVD3Wrapper(nvd3s, d3s, $q, $rootScope){
  return {
    nvd3: nvd3s,
    d3: d3s,
    discreteBarChart : function(data, config){
        var $nvd3 = this.nvd3,
            $d3 = this.d3,
            $nvd3w = this, //In order to resolve the nvd3w in other scopes.
            d = $q.defer(); //Creating a promise because chart rendering is asynchronous
        $nvd3.addGraph(function() {
          ...
        });
        return {
          chart: function() { return d.promise; } //returns the chart once rendered.
        };
    },
    _onRenderEnd: function(d, chart){
      $rootScope.$apply(function() { d.resolve(chart); });
    },
  };
}]);

myDirectives.directive('nvd3DiscreteBar', ['NVD3Wrapper', function(nvd3w){
  return {
    restrict: 'EA',
    scope: {
      data: '=' // bi-directional data-binding
    },
    link: function(scope, element, attrs) {
      var chart,
          config = {
            target: element,
          };
      var wrapper = nvd3w.discreteBarChart(scope.data, config);
      wrapper.chart().then(function(chart){
        scope.$watch(function() { return scope.data; }, function(newValue, oldValue) {
          console.log(Date.now()/1000 + ": In Directive $watch");
          if (newValue)
              chart.update();
        }, true);
      });
      //For testing
      setInterval(function(){ console.log(Date.now()/1000 + ": In Directive"); console.log(scope.data); }, 1000);
    }
  };
}]);

任何幫助將不勝感激! 非常感謝!

編輯 :新的JSFiddle與Andrew Shirley的答案: https ://jsfiddle.net/pmgq00fm/3/

添加行

$scope.$apply()

更新功能。 這是因為,當在javascript中更新變量時,除了常見的角度函數之外,角度不了解更改,因此不會浪費任何精力來刷新DOM。 這將強制執行摘要循環,從而刷新您所看到的內容。

編輯:真正了解您為什么真正使用scope.apply是非常重要的,我不認為我對它的描述非常好。 這是一篇比我做得更好的文章。

http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

我指出這一點是因為您需要注意的是,如果您位於與角度緊密相關的函數中(例如ng-click調用的內容),那么如果您嘗試使用范圍。$ apply會導致JavaScript錯誤,因為您已經處於摘要周期的中間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM