Search code examples
reactjscharts

React chartJS labels on bars


I'm working on my project and I need to show the labels of the bar chart exactly on the bars like this:

enter image description here

I can't get it to work...basically labels are never shown on the bars...they are shown above, below or not shown.

This is my current code:

    import { Bar } from 'react-chartjs-2';
    import {
      Chart,
      CategoryScale,
      LinearScale,
      BarElement,
      Title,
      Tooltip,
      Legend,
    } from 'chart.js';
    import {
      ChartName,
      ChartSubtitle,
      ChartWrapper,
    } from './HorizontalChartStyles';
    
    Chart.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend);
    
    const HorizontalChart = () => {
      const options = {
        maintainAspectRatio: true,
        indexAxis: 'y',
        elements: {
          bar: {
            borderWidth: 0,
          },
        },
        responsive: true,
        plugins: {
          legend: {
            display: false,
          },
          title: {
            display: false,
            text: 'Attendance per lecture',
          },
          tooltip: {
            enabled: false,
          },
          datalabels: {
            anchor: 'end',
            align: 'end',
            color: 'black',
            font: {
              weight: 'bold',
            },
            formatter: (value) => `${value}%`,
            labels: {
              value: {
                display: true,
              },
            },
          },
        },
        scales: {
          y: {
            display: false,
          },
          x: {
            ticks: {
              display: true,
            },
            grid: {
              display: false,
            },
            scaleLabel: {
              display: true,
              labelString: 'Percentage',
            },
          },
        },
        layout: {
          padding: {
            right: 20,
          },
        },
        text: {
          color: 'black',
          anchor: 'end',
        },
      };
    
      const labels = [
        '1. Introduction:',
        '2. HTML & CSS:',
        '3. Version Control System:',
        '4. Advanced CSS:',
        '5. Intro to JS:',
        '6. Advanced JS:',
        '7. Intro to React:',
      ];
    
      const getRandomNumber = (min, max) => {
        return Math.floor(Math.random() * (max - min + 1) + min);
      };
    
      const generateRandomData = () => {
        return labels.map(() => getRandomNumber(0, 100));
      };
    
      const getColor = (value) => {
        if (value === 100) return '#CB7B2C';
        if (value >= 90) {
          const transparency = (value - 90) / 10;
          return `rgba(203, 123, 44, ${transparency})`;
        }
        if (value >= 70) return '#CB7B2C';
        return '#DCDEDF';
      };
    
      const data = {
        labels: labels,
        datasets: [
          {
            label: 'Dataset 1',
            data: generateRandomData(),
            backgroundColor: generateRandomData().map((value) => getColor(value)),
            barPercentage: 1,
            categoryPercentage: 1,
          },
        ],
      };
    
      return (
        <ChartWrapper>
          <ChartName>Attendance per lecture (%)</ChartName>
          <ChartSubtitle>Your attendance</ChartSubtitle>
          <Bar data={data} options={options} style={{ flex: 1 }} />
        </ChartWrapper>
      );
    };
    
    export default HorizontalChart;

I tried modifying the options numerous times, nothing seemed to work. Currently my output looks like this:

enter image description here


Solution

  • const [options, setOptions] = useState({
    responsive: true,
    indexAxis: 'y',
    plugins: {
      legend: {
        display: false,
      },
      title: {
        display: false,
      },
      tooltip: {
        callbacks: {
          label: function (context) {
            const label =
              context.chart.data.labels[context.dataIndex]?.tooltip ?? '';
    
            return label;
          },
          title: function (context) {
            const title =
              context[0].chart.data.labels[context[0].dataIndex]?.label ?? '';
    
            return title;
          },
        },
      },
      datalabels: {
        color: (context) =>
          getTextColor(context.dataset.data[context.dataIndex]),
        align: 'end',
        anchor: 'center',
        formatter: function (value, context) {
          return `${
            context.chart.data.labels[context.dataIndex]?.label
          }: ${value}%`;
        },
    
        font: function () {
          return {
            size: 12,
          };
        },
      },
    },
    hover: {
      mode: null,
    },
    scales: {
      x: {
        grid: {
          display: false,
        },
      },
      y: {
        grid: {
          display: false,
        },
        ticks: {
          display: false,
          reverse: true,
        },
      },
    },
    layout: {
      padding: {
        left: window.innerWidth >= breakPoints.mobileLarge ? 24 : 0,
      },
    }, });