Only one highcharts using react-grid-layout can resize

1.1k views Asked by At

I am building a dashboard using React-Grid-Layout that will consist of grids that will house widgets (i.e. charts, calendars etc.). Each grid will be draggable, responsive and resizable (widget in grid will resize too).

My code;

import React, { Component } from "react";
import { Responsive, WidthProvider } from "react-grid-layout";
import ReactHighcharts from "react-highcharts";
import Highcharts from "highcharts/highstock";
import HighchartsReact from "highcharts-react-official";
import "./styles/styles.css";
const ResponsiveGridLayout = WidthProvider(Responsive);

const styles = {
  fontFamily: "sans-serif",
  textAlign: "center"
};

var data = [
  [1220832000000, 22.56],
  [1220918400000, 21.67],
  [1221004800000, 21.66],
  [1221091200000, 21.81],
  [1221177600000, 21.28],
  [1221436800000, 20.05],
  [1221523200000, 19.98],
  [1221609600000, 18.26],
  [1221696000000, 19.16],
  [1221782400000, 20.13],
  [1222041600000, 18.72],
  [1222128000000, 18.12],
  [1222214400000, 18.39],
  [1222300800000, 18.85],
  [1222387200000, 18.32],
  [1222646400000, 15.04],
  [1222732800000, 16.24],
  [1222819200000, 15.59],
  [1222905600000, 14.3],
  [1222992000000, 13.87],
  [1223251200000, 14.02],
  [1223337600000, 12.74],
  [1223424000000, 12.83],
  [1223510400000, 12.68],
  [1223596800000, 13.8],
  [1223856000000, 15.75],
  [1223942400000, 14.87],
  [1224028800000, 13.99],
  [1224115200000, 14.56],
  [1224201600000, 13.91],
  [1224460800000, 14.06],
  [1224547200000, 13.07],
  [1224633600000, 13.84],
  [1224720000000, 14.03],
  [1224806400000, 13.77],
  [1225065600000, 13.16],
  [1225152000000, 14.27],
  [1225238400000, 14.94],
  [1225324800000, 15.86],
  [1225411200000, 15.37],
  [1225670400000, 15.28],
  [1225756800000, 15.86],
  [1225843200000, 14.76],
  [1225929600000, 14.16],
  [1226016000000, 14.03],
  [1226275200000, 13.7],
  [1226361600000, 13.54],
  [1226448000000, 12.87],
  [1226534400000, 13.78],
  [1226620800000, 12.89],
  [1226880000000, 12.59],
  [1226966400000, 12.84],
  [1227052800000, 12.33],
  [1227139200000, 11.5],
  [1227225600000, 11.8],
  [1227484800000, 13.28],
  [1227571200000, 12.97],
  [1227657600000, 13.57],
  [1227830400000, 13.24],
  [1228089600000, 12.7],
  [1228176000000, 13.21],
  [1228262400000, 13.7],
  [1228348800000, 13.06],
  [1228435200000, 13.43],
  [1228694400000, 14.25],
  [1228780800000, 14.29],
  [1228867200000, 14.03],
  [1228953600000, 13.57],
  [1229040000000, 14.04],
  [1229299200000, 13.54]
];

var config = {
  rangeSelector: {
    selected: 1
  },
  title: {
    text: "AAPL Stock Price"
  },
  series: [
    {
      name: "AAPL",
      data: data,
      tooltip: {
        valueDecimals: 2
      }
    }
  ]
};

export default class App extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
    this.conRef = React.createRef();
  }
  render() {
    const gridItems = [
      { id: 1, name: "Item One" },
      { id: 2, name: "Item Two" }
      // { id: 3, name: "Item Three" },
      // { id: 4, name: "Item Four" },
      // { id: 5, name: "Item Five" },
      // { id: 6, name: "Item Six" },
      // { id: 7, name: "Item Seven" },
      // { id: 8, name: "Item Eight" },
      // { id: 9, name: "Item Nine" }
    ];
    const layout = [
      { i: "1", x: 0, y: 0, w: 2, h: 1, minW: 2, minH: 1 },
      { i: "2", x: 5, y: 0, w: 2, h: 1, minW: 2, minH: 1 }
      // { i: "3", x: 8, y: 0, w: 3, h: 2, minW: 2, minH: 1 },
      // { i: "4", x: 0, y: 3, w: 5, h: 2, minW: 2, minH: 1 },
      // { i: "5", x: 5, y: 3, w: 3, h: 2, minW: 2, minH: 1 },
      // { i: "6", x: 8, y: 3, w: 3, h: 2, minW: 2, minH: 1 },
      // { i: "7", x: 0, y: 6, w: 5, h: 2, minW: 2, minH: 1 },
      // { i: "8", x: 5, y: 6, w: 3, h: 2, minW: 2, minH: 1 },
      // { i: "9", x: 8, y: 6, w: 3, h: 2, minW: 2, minH: 1 }
    ];

    return (
      <ResponsiveGridLayout
        layouts={{ lg: layout }}
        measureBeforeMount={true}
        className="layout"
        // rowHeight={this.props.rowHeight}
        isDragable={true}
        isResizable={true}
        onDrag={this.onDragging}
        onDragStop={this.onMoveCard}
        margin={[20, 20]}
        onResizeStop={function (event) {
          this.myRef.current.chart.setSize(
            this.conRef.current.clientWidth,
            this.conRef.current.clientHeight
          );
          console.log("hello", event);
        }.bind(this)}
      >
        {gridItems.map((item, i) => {
          return (
            <div key={item.id} ref={this.conRef} className="grid-item">
              <HighchartsReact
                ref={this.myRef}
                containerProps={{ style: { width: "100%", height: "100%" } }}
                options={config}
                // highcharts={Highcharts}
              />
            </div>
          );
        })}
      </ResponsiveGridLayout>
    );
  }
}

Live demo on codesandbox here.

Only one chart can resize according to grid height and width change. It seems I am only passing dimension change to one div and not the rest. How do I have all charts follow grid resize instead of just one?

1

There are 1 answers

1
ppotaczek On BEST ANSWER

Your reference points only to the last created chart, you need to get the chart related with resize event, for example by callback refs:

export default class App extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
    this.conRef = React.createRef();

    this.chartRefs = [];

    this.setChartRef = (ref) => {
      this.chartRefs.push(ref);
    };
  }

  render() {
    const gridItems = [...];
    const layout = [...];

    return (
      <ResponsiveGridLayout
        ...
        onResizeStop={function (e, layout) {
          this.chartRefs[layout.i - 1].chart.reflow();
        }.bind(this)}
      >
        {gridItems.map((item, i) => {
          return (
            <div key={item.id} ref={this.conRef} className="grid-item">
              ...
              <HighchartsReact
                ref={this.setChartRef}
                containerProps={{ style: { width: "100%", height: "100%" } }}
                options={config}
                // highcharts={Highcharts}
              />
            </div>
          );
        })}
      </ResponsiveGridLayout>
    );
  }
}

Live demo: https://codesandbox.io/s/react-grid-layout-with-resizable-forked-1ftt5

API Reference: https://api.highcharts.com/class-reference/Highcharts.Chart#reflow