[英]AngularJS Data Binding - Watch cycle not triggering
Assuming the following JSFiddle: https://jsfiddle.net/pmgq00fm/1/ 假设以下JSFiddle: https ://jsfiddle.net/pmgq00fm/1/
I want my NVD3 chart to update in real time, based on the setInterval() on line 39 that updates the data the directive is bound to. 我希望基于第39行上的setInterval()来实时更新NVD3图表,该setInterval()更新指令所绑定的数据。 Here are quick pointers on the architecture and code:
以下是有关体系结构和代码的快速指导:
To debug, run the JSFiddle and open the console to see the objects and debug prints. 要调试,请运行JSFiddle并打开控制台以查看对象和调试打印。
HTML: HTML:
<div id="stats-container" ng-app="myApp" ng-controller="ThisController">
<div id="nvd3-test" nvd3-discrete-bar data="data.graph">
</div>
JS: 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);
}
};
}]);
Any help would be greatly appreciated! 任何帮助将不胜感激! Thanks a lot!
非常感谢!
EDIT : New JSFiddle with Andrew Shirley's answer: https://jsfiddle.net/pmgq00fm/3/ 编辑 :新的JSFiddle与Andrew Shirley的答案: https ://jsfiddle.net/pmgq00fm/3/
Add the line 添加行
$scope.$apply()
to the update function. 更新功能。 This is because when a variable is updated in the javascript, outside of the common angular functions, angular isn't aware of the change and therefore doesn't waste any effort refreshing the DOM.
这是因为,当在javascript中更新变量时,除了常见的角度函数之外,角度不了解更改,因此不会浪费任何精力来刷新DOM。 This forces a digest cycle which should refresh what you see.
这将强制执行摘要循环,从而刷新您所看到的内容。
EDIT: It is pretty important to actually understand why you're actually using a scope.apply and I don't feel I've described it incredibly well. 编辑:真正了解您为什么真正使用scope.apply是非常重要的,我不认为我对它的描述非常好。 Here's an article that does that much better than I have.
这是一篇比我做得更好的文章。
http://jimhoskins.com/2012/12/17/angularjs-and-apply.html http://jimhoskins.com/2012/12/17/angularjs-and-apply.html
I point this out because you need to be aware that if you ARE within a function that's closely tied to angular (eg something called by ng-click), then if you attempt to use a scope.$apply you will get javascript errors, because you'll already be in the middle of a digest cycle. 我指出这一点是因为您需要注意的是,如果您位于与角度紧密相关的函数中(例如ng-click调用的内容),那么如果您尝试使用范围。$ apply会导致JavaScript错误,因为您已经处于摘要周期的中间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.