Chad
Chad

Reputation: 35

Chart.js Auto Fit Failing

I'm running into an issue where a bar chart won't update the y- axis scale when a dataset is deselected from the legend. I'm using the 'suggestedMax' option under yAxes to add some padding to the top of the tallest bar. If I don't, the scale will just top out at the tallest bar(3500). I read the documentation and it states that suggestedMax should still auto fit the data but that's not what I'm experiencing.

Docs state the following:

The suggestedMax and suggestedMin settings only change the data values that are used to scale the axis. These are useful for extending the range of the axis while maintaining the auto fit behaviour.

Here's the chart:

var ctx1 = document.getElementById("myBarChart1")
var myBarChart = new Chart(ctx1, {
  type: 'bar',
  data: {
    labels: ['2/17','2/18','2/19','2/20','2/21','2/22'],
    datasets: [
    {
      label: "Bar 1",
      backgroundColor: "rgba(255,0,0,0.6)",
      borderColor: "rgba(255,0,0,1)",
      data: [2500,1000,1500,3500,2000,500]
    },
    {
      label: "Bar 2",
      backgroundColor: "rgba(2,117,216,0.6)",
      borderColor: "rgba(2,117,216,1)",
      data: [50,0,100,1250,500,0]
    },
    {
      label: "Bar 3",
      backgroundColor: "rgba(255,255,51,0.6)",
      borderColor: "rgba(255,255,51,0.6)",
      data: [0,0,150,250,550,200]
    },
    {
      label: "Bar 4",
      backgroundColor: "rgba(0,255,102,0.6)",
      borderColor: "rgba(0,255,102,1)",
      data: [2450,1000,1250,2000,100,0]
    },
    ],
  },
  options: {
    responsive: true,
    scales: {
      xAxes: [{
        time: {
          unit: 'day'
        },
        gridLines: {
          display: false,
          color: "white"
        },
        ticks: {
          maxTicksLimit: 6,
          fontColor: "white"
        }
      }],
      yAxes: [{
        ticks: {
          maxTicksLimit: 15,
          fontColor: "white",
          padding: 10,
          suggestedMax: 4000
        },
        gridLines: {
          display: true,
          color: "white"
        }
      }],
    },
    legend: {
      display: true,
      labels: {
        fontColor: "white",
      }
    }
  }
})

HTML:

<!-- Uses Bootstrap 4 -->
<div class="card mb-3">
  <div class="card-header">Test Status Chart</div>
  <div class="card-body" style="background: #212529">
    <canvas id="myBarChart1" width="170%" height="40%"></canvas>
  </div>
</div>

To recreate what I'm getting click 'Bar 1' in the legend, the scale should remain at max 4000 vs scaling down to the next highest number(2450).

When I remove the suggestMax option is works perfectly, minus the fact the scale tops out at 3500. I get the same issue when using the max option as well.

Any help on this would be great!

Upvotes: 1

Views: 2865

Answers (1)

swagrov
swagrov

Reputation: 1460

I have a working solution.

Define a function getMax() which takes in a chart and returns the maximum value of all the visible datasets.

var getMax = function(chart) {
    datasets = chart.data.datasets;
    max = 0;
    for(var i=0; i<datasets.length; i++) {
        dataset=datasets[i]
        if(chart.data.datasets[i].hidden) {
            continue;
        }
        dataset.data.forEach(function(d) {
            if(typeof(d)=="number" && d>max) {
                max = d
            }
        })
    }
    return max;
}

Then to options.legend, add an onClick function to call it and reset the y-axis suggestedMax to that max value plus 100 (you can tune this however you want):

  options: {
    <...>
    legend: {
      display: true,
      labels: {
        fontColor: "white",
      },
      onClick: function(e, legendItem) {
        di=legendItem.datasetIndex
        myBarChart.data.datasets[di].hidden = !myBarChart.data.datasets[di].hidden;
        myBarChart.options.scales.yAxes[0].ticks.suggestedMax=getMax(myBarChart)+100;
        myBarChart.update()
      }
    }
  }

Upvotes: 2

Related Questions