📖

MUI Data Grid の使い方と tips: ページネーションなし、検索機能、オーバーレイ

2024/10/03に公開

こんにちは、steshima です。

MUI の Data Grid はソート、フィルタリング、ページネーションなど様々な機能を備えたリッチなテーブルコンポーネントですが、高機能ゆえに指定する props なども多く、使い方をよく調べる必要があります。
この記事は Data Grid の特定のケースでの使い方や機能や tips などを備忘録も兼ねて書き残したものです。
執筆時点の Data Grid のバージョンは 7.18.0 です。

ページネーション無し

Data Grid は MUI X のプランがフリープラン(Community プラン)の場合、ページネーションの ON/OFF は切り替えられず、ページネーションを無効にすることができません。

それでも何とかフリープランでページネーション無しの状態で使いたい場合、あまり良い方法では無いかもしれませんが、1ページ目に全件を表示して表示を調整することでページネーションの無いテーブルとして表示できます。
ただしフリープランの場合、表示可能な1ページあたりの行の上限数は100件までなので、それに収まる範囲に限ります。

import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

export default function HogeComponent() {
  const { data } = useDemoData({
    dataSet: 'Commodity',
    rowLength: 5,
    maxColumns: 6,
  });

  return (
    <div style={{ height: 400, width: '100%' }}>
      <DataGrid 
        autoHeight
        columns={data.columns}
        rows={data.rows}
        slots={{
          // ページ番号などを非表示にする
          pagination: null,
        }}
      />
    </div>
  );
}

文字列検索でのデータ絞り込み

検索窓に文字列を入力して該当するデータを表示する、というよくある検索ワードでの絞り込み機能は Data Grid の Quick filter を使うことで実現できます。

Quick filter を有効にするには Data Grid 標準の <GridToolbar /> を使うか、<GridToolbarQuickFilter /> を使ってカスタマイズしたコンポーネントを使うかの二通りがあります。

下記は <GridToolbarQuickFilter /> を使った場合の例です。

import * as React from 'react';
import Box from '@mui/material/Box';
import { DataGrid, GridToolbarQuickFilter } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';
import { Stack } from '@mui/material';

declare module '@mui/x-data-grid' {
  interface ToolbarPropsOverrides extends Props {}
}

interface Props {
  label: string
}

const CustomToolBar: React.FC<Props> = ({ label }) => (
  <Stack
    direction="row"
    alignItems="center"
    justifyContent="space-between"
    padding={1}>
    <p>{label}</p>
    <GridToolbarQuickFilter
      variant="outlined"
      placeholder="検索ワードを入力"
      debounceMs={1000}
      sx={{ width: 220 }}
    />
  </Stack>
);

export default function QuickFilteringGrid() {
  const { data } = useDemoData({
    dataSet: 'Commodity',
    rowLength: 100,
    maxColumns: 6,
  });

  return (
    <Box sx={{ height: 400, width: 1 }}>
      <DataGrid
        {...data}
        columns={data.columns}
        slots={{ toolbar: CustomToolBar }}
        slotProps={{
          toolbar: {
            label: "Toolbar"
          }
        }}
      />
    </Box>
  );
}

slotProps prop では slots prop の toolbar プロパティに渡したカスタムコンポーネントに渡す props の値を指定できます。
その際、上記のように ToolbarPropsOverrides の型を定義しておくと slotProps で型推論が効くようになります。

また、Quick filter のデフォルトの挙動に少し注意が必要です。
Quick filter はユーザーの入力値に半角スペースが含まれていた場合、スペースで区切って前後を別単語として扱い、複数の検索ワードで絞り込みを行います(デフォルトでは AND 検索)。

わかりやすく、サーバーサイドで絞り込みを行う場合を例に説明します。
サーバーサイドで絞り込みを行う場合、filterModeonFilterModelChange prop を設定します。

...

const CustomToolBar: React.FC<Props> = ({ label }) => (
  <Stack
    direction="row"
    alignItems="center"
    justifyContent="space-between"
    padding={1}>
    <p>{label}</p>
    <GridToolbarQuickFilter
      variant="outlined"
      placeholder=""
      debounceMs={1000}
      sx={{ width: 200 }}
    />
  </Stack>
);

export default function QuickFilteringGrid() {
  const { data } = useDemoData({
    dataSet: 'Commodity',
    rowLength: 100,
    maxColumns: 6,
  });

  return (
    <Box sx={{ height: 400, width: 1 }}>
      <DataGrid
        {...data}
        columns={data.columns}
        slots={{ toolbar: CustomToolBar }}
        slotProps={{
          toolbar: {
            label: "Toolbar"
          }
        }}
        filterMode="server"
        onFilterModelChange={(model) => {
          // サーバーサイドへのリクエストなど
        }}
      />
    </Box>
  );
}

この状態で例えば hoge fuga という検索ワードを入力すると onFilterModelChange で下記の形式で値が渡されます。


model 引数をコンソールログに出力したもの

入力値が半角スペースで分割されて、onFilterModelChange で値を受け取る時に配列で別々のワードとして渡されています。

このロジックは <GridToolbar /><GridToolbarQuickFilter />quickFilterParser prop で上書きすることができ、例えばユーザーの入力値をスペース含めそのままサーバー側に送りたい場合は下記のように入力値そのまま配列で返して(Quick filter の仕様上配列を返す必要がある)やると、わざわざ分割されたワードを結合して...といった手間が省けます。

...
<GridToolbarQuickFilter
  variant="outlined"
  placeholder=""
  debounceMs={1000}
  sx={{ width: 200 }}
  quickFilterParser={(searchInput) => [searchInput]}
/>
...

上記は <GridToolbarQuickFilter /> で上書きした場合の例ですが、<GridToolbar /> でも同様です。

また、クライアントサイドで絞り込む場合に、半角スペース含めた完全一致で検索させたいなどあれば、上記例のようにロジックを上書きすると良いかと思います。

データが無い場合のオーバーレイ

Data Grid にはデータが無い場合のオーバーレイとして下記2種類が存在します。

  • No rows overlay
    • 表示するデータが無い場合の表示
  • No results overlay
    • Data Grid の Filtering を使って絞り込んだ状態でデータが無い場合の表示

これらは slots prop を使って表示をカスタマイズすることができます。

import * as React from 'react';
import { DataGrid } from '@mui/x-data-grid';
import Search from '@mui/icons-material/Search';
import { useDemoData } from '@mui/x-data-grid-generator';
import { Avatar, Stack, Typography } from '@mui/material';

const CustomOverlay: React.FC = () => (
  <Stack alignItems="center" height="100%" justifyContent="center">
    <Avatar
      sx={{
        width: 84,
        height: 84,
        '.MuiSvgIcon-root': {
          fontSize: '50px',
        },
      }}>
      <Search />
    </Avatar>
    <Typography sx={{ mt: 2 }}>該当データ無し</Typography>
  </Stack>
);

export default function NoResultsOverlayCustom() {
  const { data } = useDemoData({
    dataSet: 'Commodity',
    rowLength: 6,
    maxColumns: 6,
  });
  return (
    <div style={{ height: 400, width: '100%' }}>
      <DataGrid
        {...data}
        rows={[]}
        slots={{
          noRowsOverlay: CustomOverlay,
          noResultsOverlay: CustomOverlay,
        }}
      />
    </div>
  );
}

No results overlay の注意点としては、サーバーサイドで絞り込みを行う場合は絞り込み結果が0件の場合 rows prop に渡すデータが空になるため、No results overlay ではなく No rows overlay が表示されることになります。

さいごに

Data Grid はドキュメントが充実しているので基本的にそちらを参照すれば良いですが、高機能ゆえに情報量が多く、一度実装しても時間が経つと忘れてしまうことがよくあるので、この記事では複雑な部分や混乱しやすい点を書き残しました。
まだ自分自身、使いこなせていない部分も多いですが、この記事が参考になれば幸いです。

SocialPLUS Tech Blog

Discussion