0

I want a shared legend for 2 areaspline highcharts. Using react, I am unable to create that shared legend between the 2.

My code: component.js:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import AreaSplineChart from "./areaspline";
import "./App.css";

const Component = ({ data, filteredData }) => {
  const chartData = filteredData.length !== 0 ? filteredData : data;
  
 seriesOne = {"dts":["Feb 25, 2024","Feb 26, 2024","Feb 27, 2024","Feb 28, 2024","Feb 29, 2024","Mar 01, 2024","Mar 02, 2024","Mar 03, 2024","Mar 04, 2024","Mar 05, 2024","Mar 06, 2024","Mar 07, 2024"],"field":"One","legend":false,"series":[{"name":"page_views","data":[444774,484174,557434,492637,466673,409858,350902,445857,560202,554498,519825,507158],"color":"#DA70D6"},{"name":"article_views","data":[326770,340229,411025,346702,330603,297353,256416,328951,396708,392765,371077,365406],"color":"#FFD700"},{"name":"visits","data":[340812,362617,423843,371288,352045,318796,276761,347808,427239,423992,396206,391983],"color":"#6B8E23"},{"name":"return_visits","data":[156492,183181,209536,199166,186924,152693,130780,165849,217871,226510,207835,200054],"color":"#FF7F50"},{"name":"audio_play","data":[3292,3865,4913,4885,4547,4134,3762,2929,3681,4254,4444,4094],"color":"#20B2AA"},{"name":"video_play_e5","data":[687,644,457,476,776,428,572,462,1257,830,884,651],"color":"#FF8C00"}]}
 seriesTwo = {"dts":["Feb 25, 2024","Feb 26, 2024","Feb 27, 2024","Feb 28, 2024","Feb 29, 2024","Mar 01, 2024","Mar 02, 2024","Mar 03, 2024","Mar 04, 2024","Mar 05, 2024","Mar 06, 2024","Mar 07, 2024"],"field":"Two","legend":true,"series":[{"name":"page_views","data":[946159,1140360,1213841,1177459,1185913,1078396,1077760,1088569,1386531,1389498,1303569,1217209],"color":"#DA70D6"},{"name":"article_views","data":[608024,733135,788907,764644,772883,713887,740001,719234,914251,906715,851080,783937],"color":"#FFD700"},{"name":"visits","data":[678800,818550,875175,856391,865832,793614,794805,794055,1001979,995969,936937,882231],"color":"#6B8E23"},{"name":"return_visits","data":[470732,558457,580674,569857,584406,520338,491274,534849,671634,666763,629567,596229],"color":"#FF7F50"},{"name":"audio_play","data":[16255,18510,22248,24258,25180,21633,18850,15823,19976,22023,22546,22746],"color":"#20B2AA"},{"name":"video_play_e5","data":[38688,74568,84344,96184,92342,75586,39355,35294,113613,124318,104916,650926],"color":"#FF8C00"}]}
  return (
    <div className="trends clearfix w-100 column">
      <h3 className="mt-1 ms-1" style={{ color: "#81b0d2" }}>
        <u>Trends</u>
      </h3>
      <div className="clearfix w-100 column">
        <div className="clearfix w-100 column">
          <div className="w-100 oneArea">
            <AreaSplineChart
              dates={seriesOne.dts}
              nm={seriesOne.field}
              lgnd={seriesOne.legend}
              trendData={seriesOne.series}
            />
          </div>
          <div className="w-100 twoArea">
            <AreaSplineChart
              dates={seriesTwo.dts}
              nm={seriesTwo.field}
              lgnd={seriesTwo.legend}
              trendData={seriesTwo.series}
            />
          </div>
        </div>
      </div>
    </div>
  );
};

export default Component;

areaspline.js

import React, { useMemo } from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import highchartsAccessibility from "highcharts/modules/accessibility";
import highchartsExporting from "highcharts/modules/exporting";
import highchartsExportData from "highcharts/modules/export-data";
import dayjs from "dayjs";
import "dayjs/locale/es";

highchartsAccessibility(Highcharts);
highchartsExporting(Highcharts);
highchartsExportData(Highcharts);

const sharedLegendOptions = () => {
  const container = document.querySelector(".oneArea");
  var XYZ = container && container.highcharts;
  var seriesId = this.options.id;

  if (XYZ) {
    var series = XYZ.get(seriesId);
    console.log(seriesId);

    if (series) {
      series.visible ? series.hide() : series.show();
    }
  }
};
const AreaSplineChart = ({ dates, nm, lgnd, trendData }) => {
  dayjs.locale("en");
  const addCommas = (x) =>
    x.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",");

  const options = useMemo(
    () => ({
      chart: {
        type: "areaspline",
        backgroundColor: "#283347",
        zoomType: "x",
        height: "25%",
        // marginRight: 120,
        // marginLeft: -10,
      },
      exporting: {
        enabled: true,
      },
      navigation: {
        buttonOptions: {
          verticalAlign: "top",
          y: -10,
          x: -5,
        },
      },
      title: {
        text: nm,
        style: {
          color: "#fff",
        },
      },
      xAxis: {
        categories: dates,
        lineColor: "#fff",
        lineWidth: 3,
        labels: {
          style: {
            color: "#fff",
          },
        },
      },
      yAxis: {
        gridLineColor: "#283347",
        lineColor: "#fff",
        lineWidth: 3,
        labels: {
          style: {
            color: "#fff",
          },
        },
        title: {
          text: "",
        },
        opposite: false,
      },
      legend: {
        enabled: lgnd,
        itemStyle: {
          color: "#fff",
        },
      },
      accessibility: {
        enabled: false,
      },
      credits: {
        enabled: false,
      },
      tooltip: {
        backgroundColor: "#283347",
        style: { color: "#fff" },
        formatter: function () {
          const yFormat = addCommas(this.y);
          let tooltip = `
                <span><b><u>${dayjs(this.key).format(
                  "MMM DD, YYYY"
                )}</u></b>: ${yFormat}</span>`;
          return tooltip;
        },
        useHTML: true,
      },
      plotOptions: {
        series: {
          stacking: "normal",
          marker: {
            enabled: false,
            states: {
              hover: {
                enabled: true,
              },
            },
          },
          events: { legendItemClick: lgnd ? sharedLegendOptions() : undefined },
        },
      },
      series: trendData,
    }),
    [nm, dates, lgnd, trendData]
  );
  
  return (
    <HighchartsReact
      highcharts={Highcharts}
      containerProps={{ className: `${nm}-area` }}
      options={options}
    />
  );
};

export default AreaSplineChart;

I keep getting the error:

Uncaught TypeError: Cannot read properties of undefined (reading 'options')
    at sharedLegendOptions

How to create the shared legend between the 2 Highcharts.

1 Answer 1

1

The simplest way is to get a chart reference, find the correct series and call the setVisible method on it.

  const chartComponent1 = useRef(null);
  const chartComponent2 = useRef(null);

  const legendItemClick = function () {
    const seriesName = this.name;
    const chart1 = chartComponent1.current.chart;
    const chart2 = chartComponent2.current.chart;
    const series1 = chart1.series.find((s) => s.name === seriesName);
    const series2 = chart2.series.find((s) => s.name === seriesName);

    series1.setVisible();
    series2.setVisible();

    return false;
  };

Live demo: https://stackblitz.com/edit/react-yw9ctn

API Reference: https://api.highcharts.com/class-reference/Highcharts.Series#setVisible

Not the answer you're looking for? Browse other questions tagged or ask your own question.