d-_-b
d-_-b

Reputation: 23151

Chart.js how to modify an existing legend

How do I modify an existing legend in Chart.js?

I've seen complex methods of creating a custom HTML legend (using generateLegend or legendCallback), and a simple method of options.legend.legendText which should accept an array, but saw no change so assumed that was for version 1.

I'm looking to add text to the default legend:

type: 'doughnut',
data: {
    datasets: [{
        data: series,
    }],
    labels: labels,                
},
options: {
   legend: {
     legendText = labels.map((label, index) => `${label} - ${series[index]}%`);
   }
}

Upvotes: 7

Views: 10836

Answers (2)

Apostolos
Apostolos

Reputation: 10463

Chart.js 3.xx

I've included a sample for version 3.5 too. You can alter the legend text by overriding the generateLabels method.

let labels = ['a', 'b', 'c', 'd'],
  series = [4, 2, 1, 3],
  myChart = new Chart(document.getElementById('chart'), {
    type: 'doughnut',
    data: {
      labels: labels,
      datasets: [{
        data: series,
        backgroundColor: ['red', 'blue', 'green', 'orange']
      }]
    },
    options: {
      maintainAspectRatio: false,
    plugins: {
      legend: {
        display: true,
        position: "bottom",
        align: "center",
        fontFamily: "Arial",
        labels: {
          usePointStyle: true,
          fontColor: "red",
          generateLabels(chart) {
            const data = chart.data;
            if (data.labels.length && data.datasets.length) {
              const {labels: {pointStyle}} = chart.legend.options;
  
              return data.labels.map((label, i) => {
                const meta = chart.getDatasetMeta(0);
                const style = meta.controller.getStyle(i);
                
                return {
                  text: 'This is ' + label + ' - ' + chart.data.datasets[0].data[i],
                  fillStyle: style.backgroundColor,
                  strokeStyle: style.borderColor,
                  lineWidth: style.borderWidth,
                  pointStyle: pointStyle,
                  hidden: !chart.getDataVisibility(i),
  
                  index: i
                };
              });
            }
            return [];
          }
        }
    }
      }
    }
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<canvas id="chart"></canvas>

Upvotes: 4

timclutton
timclutton

Reputation: 13004

Edit:

I noticed that if the chart was redrawn (e.g. if the browser window is resized) the legend would lose the extra text.

I've modified the approach to work as an inline plugin so that the label object is modified before the legend is drawn.

let labels = ['a', 'b', 'c', 'd'],
  series = [4, 2, 1, 3],
  myChart = new Chart(document.getElementById('chart'), {
    type: 'doughnut',
    data: {
      labels: labels,
      datasets: [{
        data: series,
        backgroundColor: ['red', 'blue', 'green', 'orange']
      }]
    },
    options: {
      maintainAspectRatio: false
    },
    plugins: [{
      afterLayout: function(chart) {
        let total = chart.data.datasets[0].data.reduce((a, b) => {
          return a + b;
        });
        chart.legend.legendItems.forEach(
          (label) => {
            let value = chart.data.datasets[0].data[label.index];

            label.text += ' - ' + (value / total * 100).toFixed(0) + '%'
            return label;
          }
        )
      }
    }]
  });
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="chart"></canvas>

Upvotes: 5

Related Questions