0

I am building a project using React with a doughnut and bar chart. Working with Chart.js 3.xx.

I am trying to make my custom legend functional. I want to make data fractions disappear when the user clicks my legend items - like in the native legend, and optimally also remove the data and make the chart present it's updated data after removal.

I also use data labels to present percentage of the data on the fractions.

import ChartDataLabels from 'chartjs-plugin-datalabels';

I came across this topic: ChartJS - Show/hide data individually instead of entire dataset on bar/line charts and used this suggested code there:

function chartOnClick(evt) {
    let chart = evt.chart
    const points = chart.getElementsAtEventForMode(evt, 'nearest', {}, true);
    
    if (points.length) {
        const firstPoint = points[0];
        //var label = myChart.data.labels[firstPoint.index];
        //var value = myChart.data.datasets[firstPoint.datasetIndex].data[firstPoint.index];
        let datasetIndex = firstPoint.datasetIndex, index = firstPoint.index;
        
        if (firstPoint.element.hidden != true) {
            chart.hide(datasetIndex, index);
        } else {
            chart.show(datasetIndex, index);
        }
    }
}

options: { // chart options
    onClick: chartOnClick
}

It almost works, but the hide() method doesn't remove the fraction's percentage data label when activated, whereas when clicking the native legend it does remove it entirely.

chart

I tried looking in the plugin's docs but didn't manage to find how to remove a single label.

How can I achieve what I am looking for?

EDIT: Options Object:

export const doughnutOptsObj = {
  onClick: chartOnClick,
  responsive: true,
  maintainAspectRatio: false,
  layout: { padding: { top: 16, bottom: 16 } },
  hoverOffset: 32,
  plugins: {
    legend: {
      display: true,
      position: 'bottom',
    },
    datalabels: {
      formatter: (value, dnct1) => {
        let sum = 0;
        let dataArr = dnct1.chart.data.datasets[0].data;
        dataArr.map((data) => {
          sum += Number(data);
        });

        let percentage = ((value * 100) / sum).toFixed() + '%';
        return percentage;
      },
      color: ['#fbfcfd'],
      font: { weight: 'bold' },
      // display: false, <-- this works and makes all of the data labels disappear
    },
  },
};
XanderTEM
  • 81
  • 10
  • Having a look to the picture, it seems to me there is something else (a plugin) in doughnut chart which is drawing the percentage in the chart. Can you share the whole configuration? – user2057925 Nov 02 '22 at 12:32
  • Sure, it's the `ChartDataLabels` plugin I mentioned. Anyway I've adde my options object to the post – XanderTEM Nov 02 '22 at 15:58
  • if you have only the doughnut chart, the onClick customization sounds wrong and not for doughnut chart. If you want to hide the dataitem when you click on the dataset, the function should be changed. Let me take time to propose you something. – user2057925 Nov 02 '22 at 16:37

1 Answers1

1

It seems that the onClick function is working properly.

I have tried the attached code, leveraging on toggleDataVisibility API, and it's working as requested (codepen: https://codepen.io/stockinail/pen/abKNJqJ):

function chartOnClick(evt) {
    let chart = evt.chart
    const points = chart.getElementsAtEventForMode(evt, 'nearest', {}, true);
    
    if (points.length) {
       const firstPoint = points[0];
        chart.toggleDataVisibility(firstPoint.index);
        chart.update();
    }
}
user2057925
  • 2,377
  • 1
  • 12
  • 12
  • Thank you, `toggleDataVisibility()` was indeed the way to go and not `hide()`. Now I am presented with another problem though, would love if you check it out: https://stackoverflow.com/questions/74294444/chart-js-with-react-ctx-and-canvas-in-null-on-rerender – XanderTEM Nov 02 '22 at 19:07
  • I had a look but I'm not an expert of react :( Maybe you could create a codesandbox and publish the link in the other question. – user2057925 Nov 03 '22 at 07:42