material-table でヘッダーを固定したままスクロールできるテーブルを実装する

はじめに

テントの中から失礼します、CX 事業本部のてんとタカハシです!

テーブルを実装する際、データはスクロールできても、ヘッダーの位置は固定したいってことありますよね。ヘッダーの位置を固定することで、各列が何を表しているのかを常に把握できるようになり、使いやすいテーブルになります。今回はそれを material-table で実現してみました。

環境

環境は下記の通りです。

% sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H2

% node --version
v14.7.0

% yarn --version
1.22.10

% create-react-app --version
4.0.3

% yarn list --depth=0 | grep -e @material-ui/core -e material-table
├─ @material-ui/core@4.11.4
├─ material-table@1.69.3

デフォルトのテーブル

まずは、特別オプション等を変更せずに、デフォルトのテーブルを実装してみます。

import MaterialTable from 'material-table';

const tableData = [
  {
    couponId: '0001',
    storeName: '秋葉原店',
    couponName: '日用品 お得クーポン',
    discountRate: 10,
    startDate: '2021-06-01',
    endDate: '2021-06-07',
  },
  {
    couponId: '0002',
    storeName: '浅草店',
    couponName: '酒類 お得クーポン',
    discountRate: 5,
    startDate: '2021-06-10',
    endDate: '2021-06-20',
  },

  ...
  
  {
    couponId: '0015',
    storeName: '秋葉原店',
    couponName: '全商品 お得クーポン',
    discountRate: 3,
    startDate: '2021-10-15',
    endDate: '2021-10-30',
  },
];

const DataTable: React.FC = () => {
  return (
    <MaterialTable
      title={'クーポン一覧'}
      columns={[
        {
          title: 'クーポン ID',
          field: 'couponId',
        },
        { title: '店舗', field: 'storeName' },
        {
          title: 'クーポン名',
          field: 'couponName',
        },
        {
          title: '割引率',
          field: 'discountRate',
          cellStyle: { textAlign: 'right' },
        },
        {
          title: '利用開始日',
          field: 'startDate',
          cellStyle: { textAlign: 'right' },
        },
        {
          title: '利用終了日',
          field: 'endDate',
          cellStyle: { textAlign: 'right' },
        },
      ]}
      data={tableData}
    />
  );
};

export default DataTable;

こんな感じのテーブルになります。デフォルトでは、データが5行ずつページングされます。

20行分のデータを表示するように設定を切り替えます。

すると、テーブルが縦長になりすぎて、画面から見切れてしまいます。この状態でテーブルをスクロールしようとすると、ページ全体が下に動いてしまいます。

こんな感じです。テーブルのヘッダーが見えなくなってしまって、各列が何を表すのか分かりづらくなってしまいますね。

ヘッダーを固定する

MaterialTable の options に下記を追加します。ページング機能を OFF にして、ヘッダーを固定してあげます。

...
const DataTable: React.FC = () => {
  return (
    <MaterialTable
      title={'クーポン一覧'}
      options={{
        paging: false,
        maxBodyHeight: 600,
        headerStyle: { position: 'sticky', top: 0 },
      }}
      columns={[
      ...

これでテーブル内にスクロールバーが表示されるようになります。

スクロールしてもヘッダーは固定されたままです。良い感じですね!

おわりに

material-table の直接的なオプションとして、ヘッダーの固定を ON/OFF するようなことはできないものの、複数のオプションを組み合わせることで目的を達成することができました。こういった柔軟性が material-table の良いところですね。

今回は以上になります。最後まで読んで頂きありがとうございました!