如何在操作内部数据时触发Angular指令中的$watch
变量(例如,插入或删除数据),而不是将新对象分配给该变量?
我目前正在从JSON文件加载一个简单的数据集。我的Angular控制器执行此操作,并定义了一些函数:
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() {
};
});
我有<button>
正确调用$scope.add
函数,新对象已正确插入$scope.data
集。我每次点击“添加”按钮时,我设置的表都会更新。
<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!"
消息,但是在我点击“添加”按钮后从未收到过消息。
当我只是在$watch
对象中添加/删除对象时,如何才能触发data
事件,而不是将全新数据集分配给data
对象?< / p>
答案 0 :(得分:217)
您需要启用深层对象脏检查。 默认情况下,angular仅检查您观察的顶级变量的引用。
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);
}
}
});
见Scope。 $ watch函数的第三个参数启用深度脏检查,如果它设置为true。
请注意深度脏检查昂贵。因此,如果您只需要观看子数组而不是整个data
变量,请直接观察变量。
scope.$watch('val.children', function(newValue, oldValue) {}, true);
版本1.2.x引入了$watchCollection
Shallow监视对象的属性,并在任何属性发生更改时触发(对于数组,这意味着要观察数组项;对于对象映射,这意味着要观察属性)
scope.$watchCollection('val.children', function(newValue, oldValue) {});
答案 1 :(得分:1)
我的版本指向使用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));
}
});
}
});
答案 2 :(得分:1)
因为如果你想要深入触发你的数据,你必须通过你的听众的第3个参数true
。默认它是false
并且你的功能将会发挥作用触发,仅当您的变量不会改变它的字段。