$监视Angular指令中的数据更改
如何在Angular指令中触发一个$watch
variables来处理数据(例如,插入或删除数据),而不是将一个新的对象赋值给该variables?
我有一个简单的数据集,目前正从JSON文件加载。 我的angular度控制器做到这一点,以及定义一些function:
App.controller('AppCtrl', function AppCtrl($scope, JsonService) { // load the initial data model if (!$scope.data) { JsonService.getData(function(data) { $scope.data = data; $scope.records = data.children.length; }); } else { console.log("I have data already... " + $scope.data); } // adds a resource to the 'data' object $scope.add = function() { $scope.data.children.push({ "name": "!Insert This!" }); }; // removes the resource from the 'data' object $scope.remove = function(resource) { console.log("I'm going to remove this!"); console.log(resource); }; $scope.highlight = function() { }; });
我有一个适当调用$scope.add
函数的<button>
,并且新的对象被正确地插入到$scope.data
集合中。 每次点击“添加”button时,我设置的表格都会更新。
<table class="table table-striped table-condensed"> <tbody> <tr ng-repeat="child in data.children | filter:search | orderBy:'name'"> <td><input type="checkbox"></td> <td>{{child.name}}</td> <td><button class="btn btn-small" ng-click="remove(child)" ng-mouseover="highlight()"><i class="icon-remove-sign"></i> remove</button></td> </tr> </tbody> </table>
然而,我设置的一个指令来监视$scope.data
在所有这些情况发生时并没有被触发。
我用HTML定义了我的标签:
<d3-visualization val="data"></d3-visualization>
哪一个与下面的指令有关(修正问题的完整性):
App.directive('d3Visualization', function() { return { restrict: 'E', scope: { val: '=' }, link: function(scope, element, attrs) { scope.$watch('val', function(newValue, oldValue) { if (newValue) console.log("I see a data change!"); }); } } });
我得到了"I see a data change!"
消息在一开始,但从来没有在我点击“添加”button之后。
当我只是从data
对象中添加/删除对象时,如何才能触发$watch
事件,而不是获取要分配给data
对象的全新数据集?
您需要启用深层对象脏检查。 默认情况下,angular度只检查您所观察的顶级variables的引用。
App.directive('d3Visualization', function() { return { restrict: 'E', scope: { val: '=' }, link: function(scope, element, attrs) { scope.$watch('val', function(newValue, oldValue) { if (newValue) console.log("I see a data change!"); }, true); } } });
见范围 。 如果$ watch函数的第三个参数设置为true,则可以进行深度脏检查。
请注意深度脏检查是昂贵的 。 所以,如果你只是需要观看儿童数组而不是整个data
variables,直接观看variables。
scope.$watch('val.children', function(newValue, oldValue) {}, true);
版本1.2.x引入了$ watchCollection
浅注意一个对象的属性,并在任何属性改变时触发(对于数组,这意味着要观看数组项;对于对象映射,这意味着要注意属性)
scope.$watchCollection('val.children', function(newValue, oldValue) {});
我的版本是一个指令,它使用jqplot绘制数据一旦可用:
app.directive('lineChart', function() { $.jqplot.config.enablePlugins = true; return function(scope, element, attrs) { scope.$watch(attrs.lineChart, function(newValue, oldValue) { if (newValue) { // alert(scope.$eval(attrs.lineChart)); var plot = $.jqplot(element[0].id, scope.$eval(attrs.lineChart), scope.$eval(attrs.options)); } }); } });
因为如果你想深入触发你的数据,你必须传递你的监听器的第三个参数为true
。默认情况下它是false
,只有当你的variables变化而不是字段时,你的函数才会触发。