How can I trigger a $watch
variable in an Angular directive when manipulating the data inside (e.g., inserting or removing data), but not assign a new object to that variable?
I have a simple dataset currently being loaded from a JSON file. My Angular controller does this, as well as define a few functions:
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() {
};
});
I have a <button>
that properly called the $scope.add
function, and the new object is properly inserted into the $scope.data
set. A table I have set up does update each time I hit the "add" 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>
However, a directive I set set up to watch $scope.data
is not being fired when all this happens.
I define my tag in HTML:
<d3-visualization val="data"></d3-visualization>
Which is associated with the following directive (trimmed for question sanity):
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 get the "I see a data change!"
message at the very beginning, but never after as I hit the "add" button.
How can I trigger the $watch
event when I'm just adding/removing objects from the data
object, not getting a whole new dataset to assign to the data
object?
A - ng-bind directive binds the AngularJS Application data to HTML tags.
The angular JS $watch function is used to watch the scope object. The $watch keep an eye on the variable and as the value of the variable changes the angular JS $what runs a function. This function takes two arguments one is the new value and another parameter is the old value.
The ng-controller Directive in AngularJS is used to add a controller to the application.
Directives are classes that add additional behavior to elements in your Angular applications. Use Angular's built-in directives to manage forms, lists, styles, and what users see. See the live example / download example for a working example containing the code snippets in this guide.
You need to enable deep object dirty checking. By default angular only checks the reference of the top level variable that you watch.
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);
}
}
});
see Scope. The third parameter of the $watch function enables deep dirty checking if it's set to true.
Take note that deep dirty checking is expensive. So if you just need to watch the children array instead of the whole data
variable the watch the variable directly.
scope.$watch('val.children', function(newValue, oldValue) {}, true);
version 1.2.x introduced $watchCollection
Shallow watches the properties of an object and fires whenever any of the properties change (for arrays, this implies watching the array items; for object maps, this implies watching the properties)
scope.$watchCollection('val.children', function(newValue, oldValue) {});
Because if you want to trigger your data with deep of it,you have to pass 3th argument true
of your listener.By default it's false
and it meens that you function will trigger,only when your variable will change not it's field.
My version for a directive that uses jqplot to plot the data once it becomes available:
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));
}
});
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With