简体   繁体   中英

How to filter react-chartjs-2

I am using react-chartjs-2 in my project, and I am creating a grouped stacked bar chart with it, to remove duplicate labels I have created a custom generateLabels function, but the problem with custom generateLabels function is that when I click on chart legend (ie. Cinema) it only updates the right side (taller) chart and the left side (smaller) chart doesn't update. I know that there is onClick function but I couldn't find how to use it:

 onClick: (e, legendItem) => { let i = legendItem.datasetIndex; let ci = chRef.current.chartInstance; }
 <Bar data={data} width={100} height={50} options={options} ref={chRef} />

Is there any solutions for this? I want both charts (taller and smaller) to be updated. I have highlighted the bar chart that updates in this image: 吨

Here is my code

 import React, { useRef } from "react"; import { Bar } from "react-chartjs-2"; const mocked_data = { labels: ["Brand 1", "Brand 2", "Brand 3", "Brand 4", "Brand 5"], spend_per_channel: { spends: [ { label: "Cinema", data: [56, 23, 55, 56, 57] }, { label: "Retails", data: [22, 17, 32, 47, 62] }, { label: "Fashion", data: [46, 73, 25, 76, 27] }, { label: "Oil", data: [26, 40, 80, 50, 62] }, { label: "Gas", data: [36, 13, 35, 46, 67] } ], sales: [ { label: "Cinema", data: [156, 123, 155, 56, 157] }, { label: "Retail", data: [122, 117, 132, 147, 162] }, { label: "Fashion", data: [416, 173, 125, 176, 127] }, { label: "Oil", data: [126, 135, 180, 100, 86] }, { label: "Gas", data: [136, 113, 135, 146, 167] } ] } }; const MyChart = () => { const chRef = useRef(null); const CHART_COLORS = [ "#e35b2c", "#e77235", "#eb8a40", "#f0a04b", "#f5b858", "#f9cf63", "#fde76e", "#fced86", "#ffffb7", "#fefeeb" ]; const spendsdata = mocked_data.spend_per_channel.spends.map( (spend, index) => { return { label: spend.label, backgroundColor: CHART_COLORS[index], data: spend.data, stack: 1 }; } ); const salesdata = mocked_data.spend_per_channel.sales.map((sale, index) => { return { label: sale.label, backgroundColor: CHART_COLORS[index], data: sale.data, stack: 2 }; }); const newdataset = [spendsdata, salesdata]; const spnedperchanneldata = newdataset.flat(); const data = { labels: ["Brand 1", "Brand 2", "Brand 3", "Brand 4", "Brand 5"], datasets: spnedperchanneldata }; const options = { legend: { position: "bottom", labels: { generateLabels: function(chart) { return Chart.defaults.global.legend.labels.generateLabels .apply(this, [chart]) .filter(function(item, i) { return i > 4; }); }, boxWidth: 10, usePointStyle: true }, onClick: (e, legendItem) => { let i = legendItem.datasetIndex; let ci = chRef.current.chartInstance; } } }; return ( <> <Bar data={data} width={100} height={50} options={options} ref={chRef} /> </> ); }; export default MyChart;
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

you can check the live demo in this codesandbox demo

any help please?

You have to use state variable to save data for charts and onclick of legend modifiy the state data and send new data to bar chart Working code link

import React from "react";
import { Bar } from "react-chartjs-2";

const mocked_data = {
  labels: ["Brand 1", "Brand 2", "Brand 3", "Brand 4", "Brand 5"],
  spend_per_channel: {
    spends: [
      {
        label: "Cinema",
        data: [56, 23, 55, 56, 57]
      },
      {
        label: "Retails",
        data: [22, 17, 32, 47, 62]
      },
      {
        label: "Fashion",
        data: [46, 73, 25, 76, 27]
      },
      {
        label: "Oil",
        data: [26, 40, 80, 50, 62]
      },
      {
        label: "Gas",
        data: [36, 13, 35, 46, 67]
      }
    ],
    sales: [
      {
        label: "Cinema",
        data: [156, 123, 155, 56, 157]
      },
      {
        label: "Retail",
        data: [122, 117, 132, 147, 162]
      },
      {
        label: "Fashion",
        data: [416, 173, 125, 176, 127]
      },
      {
        label: "Oil",
        data: [126, 135, 180, 100, 86]
      },
      {
        label: "Gas",
        data: [136, 113, 135, 146, 167]
      }
    ]
  }
};

const MyChart = () => {
  const CHART_COLORS = [
    "#e35b2c",
    "#e77235",
    "#eb8a40",
    "#f0a04b",
    "#f5b858",
    "#f9cf63",
    "#fde76e",
    "#fced86",
    "#ffffb7",
    "#fefeeb"
  ];

  const spendsdata = mocked_data.spend_per_channel.spends.map(
    (spend, index) => {
      return {
        label: spend.label,
        backgroundColor: CHART_COLORS[index],
        data: spend.data,
        hidden: false,
        stack: 1
      };
    }
  );

  const salesdata = mocked_data.spend_per_channel.sales.map((sale, index) => {
    return {
      label: sale.label,
      backgroundColor: CHART_COLORS[index],
      data: sale.data,
      hidden: false,
      stack: 2
    };
  });

  const newdataset = [spendsdata, salesdata];
  const spnedperchanneldata = newdataset.flat();

  const [data, setData] = React.useState(spnedperchanneldata);
  const options = {
    legend: {
      position: "bottom",
      labels: {
        generateLabels: function(chart) {
          return Chart.defaults.global.legend.labels.generateLabels
            .apply(this, [chart])
            .filter(function(item, i) {
              return i > 4;
            });
        },
        boxWidth: 10,
        usePointStyle: true
      },
      onClick: (e, legend) => {
        onclick(legend);
      }
    }
  };

  const onclick = React.useCallback(
    legend => {
      let newData = data.map(item => {
        if (item.label === legend.text) item.hidden = !item.hidden;
        return item;
      });

      setData(newData);
    },
    [data, setData]
  );

  return (
    <>
      <Bar
        data={{
          labels: ["Brand 1", "Brand 2", "Brand 3", "Brand 4", "Brand 5"],
          datasets: data
        }}
        width={100}
        height={50}
        options={options}
      />
    </>
  );
};

export default MyChart;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM