0

I would like to move the title of my doughnut chart inside of the doughnut. I checked that I can use beforeDraw for this like here: Add text inside the Doughnut chart of the React-Chartjs-2 box to react.

However, I don't get the plugins to work with Typescript. Do I have to import something or what? I need a useState for the plugins just like setData and setOptions.

Here is my code

import {
  Chart as ChartJS,
  Tooltip,
  Legend,
  ArcElement,
  Title,
} from 'chart.js';

import { Doughnut } from 'react-chartjs-2';
import type { ChartData, ChartOptions } from 'chart.js';

ChartJS.register(
  ArcElement,
  Tooltip,
  Legend,
  Title,
);

const [data, setData] = useState<ChartData<'doughnut'>>();
const [options, setOptions] = useState<ChartOptions<'doughnut'>>();

// Data for the doughnut chart (comes from a form)
const foods = [
    { value: field1, label: 'Orange' },
    { value: field2, label: 'Banana' },
    { value: field3, label: 'Strawberry' },
  ];

  // Pie chart code here
  function PieData() {
    setData({
        labels: foods.map(food => food.label),
        datasets: [
          {
            label: 'Foods',
            data: foods.map(food => food.value),
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
            ],
            borderColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
            ],
            borderWidth: 1,
          },
        ],
    })
    setOptions({
      responsive: true,
      plugins: {
        legend: {
          position: 'right',
          rtl : true,
          labels: {
            usePointStyle: true,
            pointStyle: 'circle',
          }
        },
      },
    });
  }

<Doughnut id="pieChart" data={data} options={options}/>

I tried to add something like this:

import {
  Chart as ChartJS,
  Tooltip,
  Legend,
  ArcElement,
  Title,
  Plugin
} from 'chart.js';

...

const [plugins, setPlugins] = useState<Plugin<'doughnut'>>();

...

setOptions({
    ...
});
    
setPlugins ({
    id: "tooltipLine",
    beforeDraw: function(chart) {
      var width = chart.chart.width,
      height = chart.chart.height,
      ctx = chart.chart.ctx;
      ctx.restore();
      var fontSize = (height / 160).toFixed(2);
      ctx.font = fontSize + "em sans-serif";
      ctx.textBaseline = "top";
      var text = "Foo-bar",
      textX = Math.round((width - ctx.measureText(text).width) / 2),
      textY = height / 2;
      ctx.fillText(text, textX, textY);
      ctx.save();
    }
})
<Doughnut id="pieChart" data={data} options={options} plugins={[plugins]}/>

But it says that "Property 'chart' does not exist on type 'Chart<keyof ChartTypeRegistry, (number | [number, number] | Point | BubbleDataPoint | null)[], unknown>'.ts(2339)"

I also get another where I try to return my chart saying: "const plugins: Plugin<"doughnut", AnyObject> | undefined Type 'Plugin<"doughnut", AnyObject> | undefined' is not assignable to type 'Plugin<"doughnut", AnyObject>'. Type 'undefined' is not assignable to type 'Plugin<"doughnut", AnyObject>'.ts(2322)".

azrac
  • 29
  • 4
  • In `chart.js` v4 the first argument of plugin functions, like `beforeDraw` is the `chart` instance itself, so replace all occurrences of `chart.chart` with just `chart`. That's exactly what the typescript type error says, that `chart` is of type `Chart<...>` – kikon Jun 29 '23 at 04:42
  • Thanks! It fixed it, but I also get another error where I try to return my chart: Type 'Plugin<"doughnut", AnyObject> | undefined' is not assignable to type 'Plugin<"doughnut", AnyObject>'. Type 'undefined' is not assignable to type 'Plugin<"doughnut", AnyObject>'.ts(2322) – azrac Jun 29 '23 at 08:15
  • It comes from this one: – azrac Jun 29 '23 at 11:08
  • 1
    But I actually fixed it like this: – azrac Jun 29 '23 at 11:08

0 Answers0