Chartjs-Chart.js – Datalabels not showing using formatter

3πŸ‘

βœ…

First, this issue not related to versions (2.7 VS 2.9 and so on).
In general, please add a demo.

I guess you want this data [5,5] to display as 50% 50% and [3,3,3] ad 33% / 33% / 33%.

Your issue related to something with the calculations.

The sum looks β€œbuggy” (console.log the value).
The callback runs more than one time (One time for each label) – and you put inside loop throw array and declare this array again and again.

let dataArr: number[] = ctx.chart.data.datasets[0].data as number[];
dataArr.map((data) => {
  sum += data;
});

This example works fine (Without nested loop):

var pieChart = new Chart(ctx, {
  type: 'pie',
  data: {
    labels: ['January', 'February'],
    datasets: [{
      label: 'My First dataset',
      data: [5, 10],
      backgroundColor: ["red", "blue"]
    }]
  },
  options: {
    legend: {
      position: 'bottom',
      display: true,
    },
    plugins: {
      datalabels: {
        color: '#fff',
        display: true, 
        formatter: function (value, ctx) {
          return ((value * 100) / total(ctx)).toFixed(2) + '%';
        },
      },
    },
  },
})

function total(chart){
  let data = chart.chart.data.datasets[0].data;
  const reducer = (accumulator, currentValue) => accumulator + currentValue;
  var total = data.reduce(reducer);
  return total;
}
<div id="wrapper">
  <canvas id="ctx" width="500" height="450"></canvas>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>

<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@0.7.0/dist/chartjs-plugin-datalabels.min.js"></script>

DRY

The code above is also a little repeatable – if you declare the data outside of chart.js object you could calculate the data total only one time.

var data = [4, 9, 5, 2];
/* get total */
const reducer = (accumulator, currentValue) => accumulator + currentValue;
var total = data.reduce(reducer);

var pieChart = new Chart(ctx, {
  type: 'pie',
  data: {
    labels: ['January', 'February', 'March', 'April'],
    datasets: [{
      label: 'My First dataset',
      data: data,
      backgroundColor: ["red", "blue", "green", "violet"]
    }]
  },
  options: {
    legend: {
      position: 'bottom',
      display: true,
    },
    plugins: {
      datalabels: {
        color: '#fff',
        display: true, 
        formatter: function (value, ctx) {
          return ((value * 100) / total).toFixed(2) + '%'; 
        },
      },
    },
  },
})
<div id="wrapper">
  <canvas id="ctx" width="500" height="450"></canvas>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>

<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@0.7.0/dist/chartjs-plugin-datalabels.min.js"></script>

More dry/modular? (For changeable data) Put total data inside function and so on.

Leave a comment