Search code examples
javascriptchart.jschart.js2vue-chartjs

Changing legend text in chart js causing issues


I'm trying to shorten my chart legends, so I'm using the beforeRender plugin to change the text of the legend. However, once the chart is drawn, it seems to keep the original label size (see below snippet, legends are offset to the left instead of in the centre and if you click on orange, it toggles one of the earlier items).

The same happens if I try in beforeDraw and if I use beforeInit or beforeLayout, the legends don't seem to have been created yet.

Is there any way to get the chart to redraw the legends with the new text? Or change the legend text so that it is rendered properly?

var ctx = document.getElementById("canvas").getContext("2d");

window.myBar = new Chart(ctx, {
  type: 'pie',
  data: {
    labels: ['red - some other text that appears after', 'blue - some other text that appears after', 'green - some other text that appears after', 'orange - some other text that appears after'],
    datasets: [{
      data: [4, 2, 10, 3],
      backgroundColor: ['red', 'blue', 'green', 'orange'],
    }],
  },
  options: {
    responsive: true,
  },
  plugins: [{
    beforeRender: chart => {
      chart.legend.legendItems.forEach(label => {
        const labelParts = label.text.split(' - ');
        const newLabel = label;
        newLabel.text = labelParts[0];

        return newLabel;
      });
    },
  }],
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>

<div style="width: 100%">
  <canvas id="canvas"></canvas>
</div>


Solution

  • A better approach would be to use a custom generateLabels function like so:

    var ctx = document.getElementById("canvas").getContext("2d");
    
    window.myBar = new Chart(ctx, {
      type: 'pie',
      data: {
        labels: ['red - some other text that appears after', 'blue - some other text that appears after', 'green - some other text that appears after', 'orange - some other text that appears after'],
        datasets: [{
          data: [4, 2, 10, 3],
          backgroundColor: ['red', 'blue', 'green', 'orange'],
        }],
      },
      options: {
        responsive: true,
        legend: {
          labels: {
            generateLabels: function(chart) {
              const data = chart.data;
              if (data.labels.length && data.datasets.length) {
                return data.labels.map(function(label, i) {
                  const meta = chart.getDatasetMeta(0);
                  const style = meta.controller.getStyle(i);
    
                  return {
                    text: label.split(' - ')[0],
                    fillStyle: style.backgroundColor,
                    strokeStyle: style.borderColor,
                    lineWidth: style.borderWidth,
                    hidden: isNaN(data.datasets[0].data[i]) || meta.data[i].hidden,
    
                    // Extra data used for toggling the correct item
                    index: i
                  };
                });
              }
              return [];
            }
          }
        }
      },
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>
    
    <div style="width: 100%">
      <canvas id="canvas"></canvas>
    </div>