Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 379
Chirag B Avatar asked Nov 14 '15 14:11

Chirag B


2 Answers

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.

like image 135
Dan Crews Avatar answered Oct 10 '22 12:10

Dan Crews


I think it has relation with the id of the canvas where you are drawing. I've had this problem too amd it was because i was using the same id for the canvas of two graphs in different views. Be sure that those ids are different and that the javasrcipt of each graph is in the controller of each view or in each view itself.

Taking a look at your pluker I see that you are using the same html for the graph and I guess that when angular moves from one of your views to the other thinks that the graph is already drawn. Differentiating two graphs will solve the problem. I don't know of there is any other approach that allows using the same html for the canvas of the graph.

Hope it helps you solve it

like image 43
David Ortiz Avatar answered Oct 10 '22 11:10

David Ortiz