Search code examples
angularjsangularjs-directivechartsangularjs-ng-includechart.js

Angularjs - Charts.js: Same chart element doesn't redraw on other view


I am new to angularjs, trying to create my first directive. I am creating a directive to load Charts.js2.0(beta) into my application.

I have 2 views managed by angular-route, both html view has ng-included a html page that contains only charts-element.

The problem is the first page properly draws the chart, when i go to other view the charts div is loaded but charts is not re-drawn. And now if i go back to first view its blank.

Link to Plunker

What i am doing wrong? Is there any issue with my directive?

Thanks in advance.


Solution

  • There appears to be an issue with the Charts library modifying the existing object on the root scope, and thereby ignoring it forever afterward. I can't really trace down what is doing it, but here's a fix for you: http://plnkr.co/edit/jDQFV62FSeXAQJ6o7jE8

    Here is what you had

      scope.$watch('config', function(newVal) {
        if(angular.isDefined(newVal)) {
          if(charts) {
            charts.destroy();
          }
          var ctx = element[0].getContext("2d");
          charts = new Chart(ctx, scope.config);
          //scope.$emit('create', charts);
        }
      });
    

    Above, you can see that you're passing scope.config directly into the charts method. That appears to be modifying the data somehow, and since that's passed by reference, you're actually modifying $rootScope.sales.charts. If you copy that object and use it locally like below, you don't have that problem.

    Here's how I fixed it.

      scope.$watch('config', function(newVal) {
        var config = angular.copy(scope.config);
        if(angular.isDefined(newVal)) {
          if(charts) {
            charts.destroy();
          }
          var ctx = element[0].getContext("2d");
          charts = new Chart(ctx, config);
          //scope.$emit('create', charts);
        }
      });
    

    You can see that instead of passing that object directly in, we use angular to make a copy (angular.copy()), and that's the object we pass in.