chart.js

Conditional in ChartJS axes tick callback function isn't returning the expected labels


I have a chart containing data for each day of the year and I'm wanting to show the x-axis simply as months.

I've set up the following callback function which (crudely) grabs the month from the set of labels, checks to see whether it already exists and if not, returns it as an axis label

let rollingLabel;
...
function(label, index, labels) {
    let _label = label.replace(/[0-9]/g, '');
              
    if (rollingLabel != _label) {
        rollingLabel = _label;
        return rollingLabel;
    }
}

However, it's only returning two of the expected four labels.

What's confusing me more is that if I add console.log(rollingLabel) within the conditional I can see that the variable is updating how I'd expect but it's not returning the value, or it is and the chart isn't picking it up for whatever reason. Even more confusing is that if I uncomment line 48 // return _label the chart updates with all the labels so I don't believe it's an issue with max/min settings for the chart.

If anyone has any ideas I'd be most grateful. I've been staring at it for hours now!

The expected output for the below snippet should have the following x-axis labels:

Aug | Sep | Oct | Nov

const canvas = document.getElementById('chart');
const ctx    = canvas.getContext('2d');

let data     = [
  1,6,3,11,5,1,2,6,2,10,5,8,1,1,2,4,5,2,3,1
];

let labels = [
  "Aug 1","Aug 2","Aug 3","Aug 4","Aug 5","Sep 1","Sep 2","Sep 3","Sep 4","Sep 5","Oct 1","Oct 2","Oct 3","Oct 4","Oct 5","Nov 1","Nov 2", "Nov 3","Nov 4","Nov 5"
];

let rollingLabel;

chart = new Chart(ctx, {
  type: "line",
  data: {
    datasets: [
      {
        backgroundColor: '#12263A',
        data: data,
        pointRadius: 0
      }
    ],
    labels: labels,
  },
  options: {
    legend: {
      display: false
    },
    responsive: false,
    scales: {
      xAxes: [
        {
          gridLines: {
            display: false
          },
          ticks: {
            display: true,
            autoSkip: true,
            callback: function(label, index, labels) {
              let _label = label.replace(/[0-9]/g, '');
              
              if (rollingLabel != _label) {
                rollingLabel = _label;
                return rollingLabel;
              }
              
              // return _label;
            }
          }
        }
      ]
    },
    tooltips: {
      mode: "index",
      intersect: false
    },
    hover: {
      mode: "index",
      intersect: false
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="chart"></canvas>


Solution

  • You need to define ticks.autoSkip: false on the x-axis to make it work as expected:

    autoSkip: If true, automatically calculates how many labels can be shown and hides labels accordingly. Labels will be rotated up to maxRotation before skipping any. Turn autoSkip off to show all labels no matter what.

    Please take a look at your amended code below:

    let data     = [
      1,6,3,11,5,1,2,6,2,10,5,8,1,1,2,4,5,2,3,1
    ];
    
    let labels = [
      "Aug 1","Aug 2","Aug 3","Aug 4","Aug 5","Sep 1","Sep 2","Sep 3","Sep 4","Sep 5","Oct 1","Oct 2","Oct 3","Oct 4","Oct 5","Nov 1","Nov 2", "Nov 3","Nov 4","Nov 5"
    ];
    
    let rollingLabel;
    
    chart = new Chart('chart', {
      type: "line",
      data: {
        datasets: [
          {
            backgroundColor: '#12263A',
            data: data,
            pointRadius: 0
          }
        ],
        labels: labels,
      },
      options: {
        legend: {
          display: false
        },
        responsive: false,
        scales: {
          xAxes: [
            {
              gridLines: {
                display: false
              },
              ticks: {
                display: true,
                autoSkip: false,
                callback: function(label, index, labels) {
                  let _label = label.replace(/[0-9]/g, ''); 
                  if (rollingLabel != _label) {
                    rollingLabel = _label;
                    return rollingLabel;
                  }
                }
              }
            }
          ]
        },
        tooltips: {
          mode: "index",
          intersect: false
        },
        hover: {
          mode: "index",
          intersect: false
        }
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
    <canvas id="chart"></canvas>