Search code examples
javascriptreactjschartsbar-chartreact-chartjs

How to get element on click in Chart Js?


I'm adding Chart Js in my react app to display data as bar chart. The code works and I can display data correctly, the only issue I'm facing is that if one of the data values is too high, bar chart will only display it

enter image description here

As you can see on this image, if data for January is 100,000 and for other months it's less than 10,000, we can only see data for January. When I click on element for data (January) I get index 0, I need to get index for all elements for other months, for example when I click on white space for February I should get index 1 etc.

Code Sandbox - link

My code:

import React, { useRef } from "react";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
} from "chart.js";
import { Bar, getElementAtEvent } from "react-chartjs-2";

ChartJS.register(
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
);

export const options = {
  responsive: true,
  plugins: {
    legend: {
      position: "top"
    },
    title: {
      display: true,
      text: "Chart.js Bar Chart"
    }
  }
};

const labels = ["January", "February", "March", "April", "May", "June", "July"];

export const data = {
  labels,
  datasets: [
    {
      label: "Dataset 1",
      data: [100000, 500, 40],
      backgroundColor: "rgba(255, 99, 132, 0.5)"
    }
  ]
};

export default function App() {
  const barRef = useRef();

  const handleGetData = (event) => {
    console.log(getElementAtEvent(barRef.current, event)[0]?.index);
  };

  return (
    <Bar ref={barRef} options={options} data={data} onClick={handleGetData} />
  );
}

How can I get the index for February in this case? If I click on white space, getElementAtEvent(barRef.current, event)[0]?.index returns undefined.


Solution

  • The index of the bar element corresponds to its numeric x value, so to get the index corresponding to a click event you just have to convert the event's clientX from pixel to "real" values.

    If we get hold of the Chart object, as

    const chart = barRef.current;
    

    we can get the x value for a click event using:

    const xClick = chart.scales.x.getValueForPixel(event.nativeEvent.offsetX);
    

    this goes from 0 to how many categories you defined for the x axis.

    To get the BarElement instance (and to see that there is a bar at that index) you can use

    const barElement = chart.getDatasetMeta(0).data[xClick];
    

    which might be undefined if there's no bar there. Here's a fork of your codesandbox with these changes.