【Material-UI DataGrid】セル内のレンダリング、行選択、クリックイベントについて

# 前提条件

インストール方法と基本的な使い方について書きます。必要なければ以下のリンクで飛べます。

- [セル内のレンダリング](#セル内のレンダリング) 
  - セル内にコンポーネントを配置する方法
- [行選択](#行選択) 
  - 行選択のための prop
- [クリックイベント](#クリックイベント)
  -  クリックイベントで関数を実行する方法
  -  選択した行を state として保持する方法

## インストール

必要なパッケージをインストールします。

```
npm install @mui/material @emotion/react @emotion/styled
```

```
npm install @mui/x-data-grid
```

必要なパッケージのインストールについては以下に記載があります。

https://mui.com/x/react-data-grid/getting-started/

## 基本的な使い方

行を定義する `rows`、列を定義する `columns` にそれぞれ配列を渡します。

```react
<DataGrid rows={rows} columns={columns} />
```

行と列の配列は以下のようなフォーマットです。列の `field` プロパティと、行の各オブジェクトのプロパティを紐づけます。

```react
const rows = [
  { id: 1, col1: 'A', col2: 'B' },
  { id: 2, col1: 'C', col2: 'D' },
  { id: 3, col1: 'E', col2: 'F' },
];

const columns = [
  { field: 'col1', headerName: 'Column Name 1', width: 150 },
  { field: 'col2', headerName: 'Column Name 2', width: 150 },
];
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/ff59e4e1-ebbd-ee1b-0692-3757c771be83.png)

完全なコードはこちらに置きました。

https://github.com/quryu-1/mui-datagrid-example/tree/main/example/first-sample

行のキーは　`field` プロパティの値に一致する必要があります。例えば、`field: 'xxx'` とすると、その列の値は正常に表示されなくなります。

```react
const rows = [
  { id: 1, col1: 'A', xxx: 'B' }, // col2 => xxx
  { id: 2, col1: 'C', col2: 'D' },
  { id: 3, col1: 'E', col2: 'F' },
];

const columns = [
  { field: 'col1', headerName: 'Column Name 1', width: 150 },
  { field: 'col2', headerName: 'Column Name 2', width: 150 },
];
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/c2e86310-90eb-4210-2099-d855b6ea980c.png)

columns に格納する列のオブジェクトは、格納する順序と表示される順序が一致します。

> By default, columns are ordered according to the order they are included in the columns array.

https://mui.com/x/react-data-grid/column-ordering/

```react
const rows = [
  { id: 1, col1: 'A', col2: 'B' },
  { id: 2, col1: 'C', col2: 'D' },
  { id: 3, col1: 'E', col2: 'F' },
];

const columns = [
  // 入れ替える
  { field: 'col2', headerName: 'Column Name 2', width: 150 },
  { field: 'col1', headerName: 'Column Name 1', width: 150 },
];
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/ccf0931f-04b0-55e0-2458-c06f8c08a5f8.png)

# セル内のレンダリング

セルにコンポーネントを入れたいとき、列オブジェクトに `renderCell` プロパティを定義します。

https://mui.com/x/react-data-grid/column-definition/#rendering-content

```react
const rows = [
  { id: 1, col1: 'A', col2: { popTitle: 'B', popMessage: 'This cell is B.' } },
  { id: 2, col1: 'C', col2: { popTitle: 'D', popMessage: 'This cell is D.' } },
  { id: 3, col1: 'E', col2: { popTitle: 'F', popMessage: 'This cell is F.' } },
];

const getPopOver = props => {
  const { popTitle, popMessage } = props.value;
  return (
    // セルにこのようなポップオーバーコンポーネントをレンダリングさせたい
    <MouseOverPopover popTitle={popTitle} popMessage={popMessage} />
  );
}

const columns = [
  { field: 'col1', headerName: 'Column Name 1', width: 150 },
  {
    field: 'col2', headerName: 'Column Name 2', width: 150,
    renderCell: props => getPopOver(props), // renderCell プロパティを定義する
  },
];
```

![Qiita-gif用 (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/7f759a27-45fe-499f-3fa3-00094cc3fc5f.gif)

完全なコードはこちらに置きました。

https://github.com/quryu-1/mui-datagrid-example/tree/main/example/popover

ポップオーバーに関する MUI コンポーネントは以下にあります。

https://mui.com/material-ui/react-popover/

# 行選択

セレクトチェックボックスを追加するには、`checkboxSelection={true}` を追加します。

```react
<DataGrid
  rows={rows}
  columns={columns}
  checkboxSelection={true}
/>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/5baa31ed-2954-585c-e5bc-5010e5a5d6b0.png)

チェックボックスのみクリックすることによって、チェックを入れるようにしたい場合（この状態では行のどこをクリックしてもチェックが入る）、`disableSelectionOnClick={true}` を追加します。

```react
<DataGrid
  rows={rows}
  columns={columns}
  checkboxSelection={true}
  disableSelectionOnClick={true}
/>
```

# クリックイベント

## クリックイベントで関数を実行する方法

セルをクリックされたときにイベントを発生させる場合は、`onCellClick` を用います。

```react
<DataGrid
  rows={rows}
  columns={columns}
  checkboxSelection={true}
  disableSelectionOnClick={true}
  onCellClick={(event) => cellClickHandler(event)}
/>
```

https://mui.com/x/api/data-grid/data-grid/#props

チェックボックスがクリックされた銅貨を判定するには以下のように比較します。

```react
event.field === '__check__'
```

クリックされた行の id を取得するには `onSelectionModelChange` を用います。

```react
<DataGrid
  rows={rows}
  columns={columns}
  checkboxSelection={true}
  disableSelectionOnClick={true}
  onCellClick={(event) => cellClickHandler(event)}
  onSelectionModelChange={(id) => setSelectionModel(id)}
/>
```

以下は選択された行を別のテーブルに表示するサンプルです。

![Qiita-gif用 (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/9ccb33e4-05db-f37d-984c-e2084537cb5a.gif)

完全なコードはこちらに置きました。

https://github.com/quryu-1/mui-datagrid-example/tree/main/example/select-table

## 選択した行を state として保持する方法

以下のサンプルでは、`onSelectionModelChange` によって行選択時にその行の `id` を格納した配列 `newSelectionModel` を引数として、関数を実行できます。ここでは、`setSelectionModel` というフック関数を実行しています。`selectionModel` には、テーブル表示時にあらかじめ選択したい行の `id` を渡します。

```react
const [selectionModel, setSelectionModel] = useState([]);

<DataGrid
  checkboxSelection
  onSelectionModelChange={(newSelectionModel) => {
    setSelectionModel(newSelectionModel);
  }}
  selectionModel={selectionModel}
  {...data}
/>
```

これを使用すると、例えばモーダルにテーブルを表示したいときにモーダルを閉じたとしても選択した行を保持することができます。

![Qiita-gif用 (5).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/cff7fad4-764a-45e4-e931-a310e5e182d5.gif)

完全なコードはこちらに置きました。

https://github.com/quryu-1/mui-datagrid-example/tree/main/example/selectionmodel

# 参考記事

https://mui.com/x/react-data-grid/

https://mui.com/x/api/data-grid/data-grid/

https://mui.com/x/react-data-grid/column-definition/

https://mui.com/x/react-data-grid/selection/

https://mui.com/material-ui/react-popover/