user2912840 user2912840 - 10 months ago 70
AngularJS Question

AngularJS: How do I get a directive to update when the data changes?

I am trying to get a directive to update when the data changes in my controller... currently I have gotten the ng-repeat to update some of the values but the directive inside the repeat does not appear to get called again.

I have a directive like so:

app.directive("donut", function () {
return {
restrict: 'E',
scope: {
donut: '='
replace: true,
link: link

function link($scope, $elem, $attr) {
var chart = {
//chart functionality
$scope.$watch($scope.donut,function(){chart.createChart($elem, $scope.donut)});

I have this in my html:

<donut class="donut-holder-inventory" donut="data.donutData"></donut>

And then I have this in the controller:

$scope.regions = [
region: 'Team Number One',
data: [
title: 'Number One',
subtitle: 'Quantity Available',
daysSupply: 0,
targetNumber: 108,
actualNumber: 46,
targetPercentage: 1,
actualPercentage: 0,
color: 'red',
donutData: {
name: 'Number One',
fullscale: false,
fullsection: 108,
values: [46],
labeltext: ['% to goal'],
labelunits: "percent",
color: ["#f44336"],
labels: false,
height: 150

Then I have this timeout in the controller just to test the data binding:

function timerFunc(dat) {
$scope.$apply(function () {
var dat = $scope.regions;
for (var x = 0; x < dat.length; x++) {
var cdat = dat[x].data;
for (var c = 0; c < cdat.length; c++) {
var nval = Math.round($scope.regions[x].data[c].actualNumber + (Math.random() * 1000))
$scope.regions[x].data[c].targetNumber = nval;
$scope.regions[x].data[c].donutData.fullsection = nval;
var timer = setInterval(function () {
}, 1000);

The donut directive is bound to the .donutData property, the rest of the view updates but the donut directive does not, what do I need to do to make the directive run its link function again?


Call $watch with true as the third argument:

 $scope.$watch("donut", function(){chart.createChart($elem, $scope.donut)}, true);

By default when comparing two complex objects in JavaScript, they will be checked for "reference" equality, which asks if the two objects refer to the same thing, rather than "value" equality, which checks if the values of all the properties of those objects are equal.