Reactのテーブルライブラリ「AG Grid」でレスポンシブにテーブルをリサイズする件

「R」で作った心理尺度ツールは公開する際のライセンスの問題が気になったので、思い切って勉強を兼ねてReactであらためて作ることにした。

テーブル作成のためどのライブラリを使うかを調査した結果「AG Grid」が今回の目的にフィットしそうなのでこれを使うことに決定。

とりあえず、ローカルからCSVを読み込んでデータをStateに保存して確認用の画面に出力する部分を作った。このとき、レスポンシブにテーブル(含むカラムの幅)をコントロールする方法を調査したのでメモしておく。

その際、以下のページを参考にした。

まだTypescriptの型の使い方がこなれていないのでAny指定がアレですが、とりあえず以下の感じで作成したところいい感じで動くことを確認できた。

Propsの dataOriginalに読み込んだCSVがオブジェクトのArrayで入っています。これをcontext provider でグローバルに渡しています。

QuickDataViewerのプロップスは読み込んだCSVのヘッダーがArrayで渡されてきます。

ポイントは

onGridColumnsChanged={() => gridColumnApi && autoSizeAll(false)}

これをいれたらいい感じでリサイズできます。

import { memo, useState, VFC } from "react";

import { Box, Heading } from "@chakra-ui/layout";
import { AgGridColumn, AgGridReact } from "ag-grid-react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-alpine.css";

import { useDataOriginal } from "../../providers/useDataOriginalProvider";

type Props = {
  fileHeader: Array<string>;
};

export const QuickDataViewer: VFC<Props> = memo((props) => {
  const { fileHeader } = props;
  const { dataOriginal } = useDataOriginal();

  const [gridColumnApi, setGridColumnApi] = useState<any>(null);

  const onGridReady = (params: any) => {
    setGridColumnApi(params.columnApi);
  };

  const defaultColDef = {
    // set every column width
    width: 100,
    floatingFilter: false,
    resizable: true,
    sortable: false,
    filter: false,
  };

  window.onresize = () => {
    autoSizeAll(false);
  };

  const autoSizeAll = (skipHeader: boolean) => {
    let allColumnIds: Array<string> = [];
    gridColumnApi.getAllColumns().forEach(function (column: any) {
      allColumnIds.push(column.colId);
    });
    gridColumnApi.autoSizeColumns(allColumnIds, skipHeader);
  };

  return (
    <>
      <Heading as="h2" size="md" mb={4}>
        QUICK DATA VIEW
      </Heading>
      <Box className="ag-theme-alpine" style={{ height: "100%", width: "80%" }}>
        <AgGridReact
          onGridReady={onGridReady}
          rowData={dataOriginal}
          // rowHeight={30}
          defaultColDef={defaultColDef}
          onGridColumnsChanged={() => gridColumnApi && autoSizeAll(false)}
          pagination={true}
        >
          {fileHeader.map((row) => (
            <AgGridColumn key={row} headerName={row} field={row} />
          ))}
        </AgGridReact>
      </Box>
    </>
  );
});