Material UIのDataGridで、チェックボックス選択した行の行情報全て取得してみた

2022.09.30

こんにちは、こんばんわ。 「ゴルフコンペでニアピン賞を取ってテンション上がっています。」 どうも、CX 事業本部 Delivery 部 MAD グループ@札幌の hiro です。

今回は、「MUI(Material UI)(以後、MUIと省略)でDataGridを触れているときに、チェックボックスで行選択をしたときの行全体の情報を取得しましたブログ」を執筆します。

はじめに

DataGridとonSelectionModelChangeについて

MUIで用意されているDataGridは、表をいい感じ表示してくれて、さまざまなAPIを用意することで多機能を実現しているコンポーネントです。

このDataGridのpropsの中に、「onSelectionModelChange」が存在します。

この「onSelectionModelChange」は、「selectionModel」propを使用して、選択範囲を制御します。このプロップが変更されるたびに、新しい選択値で「onSelectionModelChange」コールバックが呼び出される感じです。 選択した行情報を特定したいときなどに利用します。

onSelectionModelChangeで少し困ったこと

「onSelectionModelChange」を利用して行を特定する際に、以下のようにしてもIDのみが表示されて、行に関する情報が取得できません。

<DataGrid
  rows={rows}
  onSelectionModelChange={(newSelectionModel) => {
    // newSelectionModelには行のIDだけが入っている
    console.log(newSelectionModel);
  }}
/>

そこで、チェックボックスで行選択したときに、行情報全体を取得できるようにしてみた内容を記述しています。

注意

いくつか注意点があります。

  • 見た目などは一切考慮していないです
  • Reactが動作する環境の上に作成しています
  • 今回、MUIでもテンプレートを提供しているので、そちらのテンプレートを利用して構築しています※
  • etc

参考

ご了承ください。

事前準備

□ 環境構築とライブラリのインストール

  • React環境整え
$ npx create-react-app web --template typescript
$ cd web
  • MUIインストール
$ npm install @mui/material @emotion/react @emotion/styled @mui/x-data-grid

参考

やってみよう

今回もやってみようということで、ファイル構成やファイル内容を記述していきたいと思います。

□ ファイル構成

以下のファイル構成で、記述します。 一つのファイルで完結させているので、記述するか迷いましたが、念の為記載しています・・・

.
└── App.tsx・・・onSelectionModelChangeで行情報全体取得と全体レンダリング

□ onSelectionModelChangeで行情報全体取得と全体レンダリング

チェックボックスで行選択したときに、行情報全体を取得できるようにするには、選択された行にそれぞれに付与されるIDとnew Set()を用いてrowsから特定しています。

<DataGrid
  rows={rows}
  onSelectionModelChange={(RowId) => {
    // 選択された行を特定するための処理
    const selectedRowId = new Set(RowId);
    const selectedRows = rows.filter((dataGridRow) =>
      selectedRowId.has(dataGridRow.id)
    );
    setSelectionModel(selectedRows);
  }}
/>

全体の内容としては以下になります。

App.tsx

import * as React from "react";
import AppBar from "@mui/material/AppBar";
import CssBaseline from "@mui/material/CssBaseline";
import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import { DataGrid, GridColDef, GridValueGetterParams } from "@mui/x-data-grid";
import { Box } from "@mui/material";

interface rowInterface {
  id: number;
  lastName: string | null;
  firstName: string | null;
  age: number | null;
}

const columns: GridColDef[] = [
  { field: "id", headerName: "ID", width: 150 },
  {
    field: "firstName",
    headerName: "First name",
    width: 150,
    editable: true,
  },
  {
    field: "lastName",
    headerName: "Last name",
    width: 150,
    editable: true,
  },
  {
    field: "age",
    headerName: "Age",
    type: "number",
    width: 110,
    editable: true,
  },
  {
    field: "fullName",
    headerName: "Full name",
    description: "This column has a value getter and is not sortable.",
    sortable: false,
    width: 160,
    valueGetter: (params: GridValueGetterParams) =>
      `${params.row.firstName || ""} ${params.row.lastName || ""}`,
  },
];

const rows: rowInterface[] = [
  { id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
  { id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
  { id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
  { id: 4, lastName: "Targaryen", firstName: "Daenerys", age: null },
  { id: 5, lastName: "Melisandre", firstName: null, age: 150 },
];

const theme = createTheme();

const DataGridUnique = () => {
  const [selectionModel, setSelectionModel] = React.useState<rowInterface[]>(
    []
  );
  console.log(">>> selectionModel: ", selectionModel);

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <AppBar position="relative">
        <Toolbar>
          <Typography variant="h6" color="inherit" noWrap>
            Album layout
          </Typography>
        </Toolbar>
      </AppBar>
      <main>
        <Box sx={{ height: 400, width: "100%" }}>
          <DataGrid
            rows={rows}
            columns={columns}
            pageSize={5}
            rowsPerPageOptions={[5]}
            checkboxSelection
            disableSelectionOnClick
            experimentalFeatures={{ newEditingApi: true }}
            onSelectionModelChange={(RowId) => {
              // 選択された行を特定するための処理
              const selectedRowId = new Set(RowId);
              const selectedRows = rows.filter((dataGridRow) =>
                selectedRowId.has(dataGridRow.id)
              );
              setSelectionModel(selectedRows);
            }}
          />
        </Box>
      </main>
    </ThemeProvider>
  );
};

export default DataGridUnique;

□ 再動作確認

記述した内容で、サーバーを動かします。

$ npm run start

おわりに

今回、MUIのDataGridで選択した行の全情報を取得したかったときに、行IDのみしか抽出されなかったため、少し手を加えて抽出しました。

ありがとうございました。