jtblin / angular-chart.js

Reactive, responsive, beautiful charts for AngularJS using Chart.js: http://jtblin.github.io/angular-chart.js
Other
2.67k stars 759 forks source link

Empty Charts Aren't Updated Properly #28

Closed djgadd closed 9 years ago

djgadd commented 9 years ago

Chartjs won't (as I understand it) draw a chart with empty values (whether that be nulls or 0's), and it won't update a chart that hasn't been drawn. As a result, when instantiating a chart with all 0's the chart never actually updates when it's data changes.

Unfortunately I haven't got an example on hand, but it should be fairly easy to replicate with the example code in the readme if you change the initial values to 0; I've only tested this with pie and donut charts too.

I couldn't find a way to check if the chart has already been drawn, so a quick fix was to check to see if oldVal > 0 in canUpdateChart:

function canUpdateChart(type, newVal, oldVal) {
  if (newVal && oldVal && newVal.length && oldVal.length) {
    if(oldVal.reduce(function(carry, val){return carry+val;}, 0) > 0)
      return hasDataSets(type) ?
        newVal.length === oldVal.length && newVal[0].length === oldVal[0].length :
        newVal.length === oldVal.length;
    else
      return false;
  }
  return false;
}
jessegreathouse commented 9 years ago

I have this problem also. It's really annoying. I wish i could figure out how to fix it. I have a site which displays different charts for every day, and you can flip through each day just find unless you start with a day that has no data yet, and then the chart never shows up.

jtblin commented 9 years ago

Could you please post a jsbin or similar to reproduce the problem? I am not able to repro with the line chart example in examples/charts.html and examples/app.js setting all the data to 0 initially.

      <div class="col-lg-6 col-sm-12" id="line-chart" ng-controller="LineCtrl">
          <div class="panel panel-default">
            <div class="panel-heading">Line Chart</div>
            <div class="panel-body">
             <canvas id="line" class="chart chart-line" data="data" 
               labels="labels" series="series">
             </canvas>
            </div>
          </div>
        </div>
      </div>
app.controller("LineCtrl", ['$scope', '$timeout', function ($scope, $timeout) {
    $scope.labels = ["January", "February", "March", "April", "May", "June", "July"];
    $scope.series = ['Series A', 'Series B'];
    $scope.data = [
      [0, 0, 0, 0, 0, 0, 0],
      [0, 0, 0, 0, 0, 0, 0]
    ];
    $timeout(function () {
      $scope.data = [
        [28, 48, 40, 19, 86, 27, 90],
        [65, 59, 80, 81, 56, 55, 40]
      ];
    }, 3000);
}]);

The chart is correctly displayed once the timeout kicks in and the data is updated after 3 seconds.

image

jtblin commented 9 years ago

Here is a jsbin template for convenience: http://jsbin.com/dufibi/3/edit?html,js,output.

djgadd commented 9 years ago

Sorry I didn't have time to create an example or a pull request when I originally posted this, I just wanted to quickly share my solution.

Example of the problem: http://jsbin.com/bobanojoxa/1/edit?html,js,output

Appears to only be pie and doughnut charts that are affected.

HTH.

jessegreathouse commented 9 years ago

I think it has something to do with initializing a pie and doughnut with zero. The other charts can handle being initialized with zero but a pie has to divide by the members of it's collection and since you can't divide by zero then it must cause some type of unrecoverable failure. This might be a chart.js issue and not an angular-chartjs issue.

djgadd commented 9 years ago

Dividing by 0 in JS gives the result of Infinity, it causes no error in chart.js, in my opinion it's behaviour (not to render the pie/doughnut) is a the expected behaviour. The 'problem' arises because the chart.js update method obviously only applies to charts that have been rendered, again expected behaviour.

I think when you consider the above, chart.js is arguably functioning as expected. There is a strong case for changing the way update works so that it does render the chart if it hasn't previously, but that could take a while (I'm unfamiliar with how quickly they turn around feature changes).

Until then the above is a working solution for angular-chartjs.

jtblin commented 9 years ago

Thanks for the repro and detailed report. Your code worked but had for side effect to always destroy and create line/bar/etc. charts as the dataset is different in these cases (multidimensional arrays). I've slightly changed the code and pushed 0.3.15.

djgadd commented 9 years ago

Awesome, thanks!