目次
概要
shadcn/ui の Table コンポーネントにフィルタ機能を実装する方法を解説します。
前提
以下のコードは React – shadcn/ui の Table コンポーネントについて解説 | pystyle で作成した動的なテーブルの実装の機能追加になります。 まず、上記のページでテーブルを実装し、そのコードに以下のコードを追加してください。
フィルタ機能を実装する
1. Input コンポーネントを追加
ページ遷移ボタンの実装には、Input コンポーネントを使用するため、インストールします。
npx shadcn@latest add input
2. フィルタ機能の追加
テーブルを実装した src/payment/payment-table.tsx
を以下のように変更します。
src/payment/payment-table.tsx
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
getFilteredRowModel,
ColumnFiltersState, // 追加
} from "@tanstack/react-table";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Input } from "@/components/ui/input"; // 追加
import React from "react";
interface PaymentTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
}
export function PaymentTable<TData, TValue>({
columns,
data,
}: PaymentTableProps<TData, TValue>) {
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(), // 追加
onColumnFiltersChange: setColumnFilters, // 追加
state: {
columnFilters, // 追加
},
});
return (
<div>
{/* Filtering */}
<div className="flex items-center">
<Input
placeholder="Email をフィルタ..."
value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
</div>
{/* Table */}
<div className="mt-3 border rounded-md">
<Table>
{/* Header */}
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
{/* Body */}
<TableBody>
{table.getRowModel().rows?.length ? (
// データが存在する場合
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
// データが存在しない場合
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
データなし
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
);
}
解説
詳しくは Column Filtering Guide | TanStack Table Docs を参照してください。
フィルタ状態を管理するための state を作成し、table のフィルタ状態と連携します。
- onColumnFiltersChange: テーブルのフィルタ状態が変更された場合に呼ばれるコールバック関数を設定します。
- state.columnFilters: フィルタ状態を管理する state を設定します。
- getFilteredRowModel: フィルタ状態に応じた行モデルを取得する関数を設定します。
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
);
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(), // 追加
onColumnFiltersChange: setColumnFilters, // 追加
state: {
columnFilters, // 追加
},
});
ユーザーがフィルタを入力するための入力欄を追加します。
<div className="flex items-center">
<Input
placeholder="Email をフィルタ..."
value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
</div>
コメント