0

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 () {
        console.log("changing")
        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++) {
                console.log(cdat[c].targetNumber)
                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 () {
    timerFunc()
}, 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?

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Does It work the first time? And just doesn't update your changes?
Yes, on page load it does work, and it worked on page load before adding true as well. When I update the data with the timer function the ng-repeat updates its template but the donut directive contained within that repeat does not update...
And you are sure, that the $watch function isn't call after changing donutData? Maybe the problem is inside createChart().
I put a console.log in the watch function, it only triggers the first time the chart is created on page load...
What happens if you write $scope.$watch("donut", function()...)?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.