数据表
使用 TanStack Table 构建强大的表格和网格。
Status | Amount | |||
---|---|---|---|---|
success | ken99@yahoo.com | $316.00 | ||
success | Abe45@gmail.com | $242.00 | ||
processing | Monserrat44@gmail.com | $837.00 | ||
success | Silas22@gmail.com | $874.00 | ||
failed | carmella@hotmail.com | $721.00 |
简介
我创建的每个数据表或网格都是独一无二的。它们的行为各不相同,具有特定的排序和筛选要求,并使用不同的数据源。
将所有这些变体组合到单个组件中是没有意义的。如果我们这样做,我们将失去 无头 UI 提供的灵活性。
因此,与其使用数据表组件,我认为提供有关如何构建自己的数据表的指南会更有帮助。
我们将从基本 <Table />
组件开始,并从头开始构建一个复杂的数据表。
**提示:**如果您发现自己在应用程序中的多个位置使用同一张表格,则可以随时将其提取到可重用的组件中。
目录
本指南将向您展示如何使用 TanStack Table 和 <Table />
组件来构建您自己的自定义数据表。我们将介绍以下主题:
安装
- 将
<Table />
组件添加到您的项目:
npx shadcn-ui@latest add table
- 添加
tanstack/react-table
依赖项:
npm install @tanstack/react-table
先决条件
我们将构建一个表格来显示最近的付款。以下是我们数据的样子:
type Payment = {
id: string
amount: number
status: "pending" | "processing" | "success" | "failed"
email: string
}
export const payments: Payment[] = [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "m@example.com",
},
{
id: "489e1d42",
amount: 125,
status: "processing",
email: "example@gmail.com",
},
// ...
]
项目结构
首先创建以下文件结构:
app
└── payments
├── columns.tsx
├── data-table.tsx
└── page.tsx
我这里使用的是 Next.js 示例,但这适用于任何其他 React 框架。
columns.tsx
(客户端组件)将包含我们的列定义。data-table.tsx
(客户端组件)将包含我们的<DataTable />
组件。page.tsx
(服务器组件)是我们获取数据并呈现表格的地方。
基本表格
让我们从构建一个基本表格开始。
列定义
首先,我们将定义我们的列。
"use client"
import { ColumnDef } from "@tanstack/react-table"
// 此类型用于定义我们数据的外观。
// 您可以在此处使用 Zod 架构(如果您愿意)。
export type Payment = {
id: string
amount: number
status: "pending" | "processing" | "success" | "failed"
email: string
}
export const columns: ColumnDef<Payment>[] = [
{
accessorKey: "status",
header: "Status",
},
{
accessorKey: "email",
header: "Email",
},
{
accessorKey: "amount",
header: "Amount",
},
]
**注意:**列是您定义表格核心内容的位置。它们定义将显示的数据,如何对其进行格式化、排序和筛选。
<DataTable />
组件
接下来,我们将创建一个 <DataTable />
组件来渲染我们的表格。
"use client"
import {
ColumnDef,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]
data: TData[]
}
export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<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">
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
)
}
**提示:**如果您发现在多个地方使用 <DataTable />
,则这部分是将组件提取到 components/ui/data-table.tsx
中使之可重用的部分。
<DataTable columns={columns} data={data} />
呈现表格
最后,我们将在页面组件中呈现我们的表格。
import { Payment, columns } from "./columns"
import { DataTable } from "./data-table"
async function getData(): Promise<Payment[]> {
// 从您的 API 中获取数据。
return [
{
id: "728ed52f",
amount: 100,
status: "pending",
email: "m@example.com",
},
// ...
]
}
export default async function DemoPage() {
const data = await getData()
return (
<div className="container mx-auto py-10">
<DataTable columns={columns} data={data} />
</div>
)
}
单元格格式化
让我们将金额单元格格式化为显示美元金额。我们还将把单元格右对齐。
更新列定义
更新金额的 header
和 cell
定义,如下所示:
export const columns: ColumnDef<Payment>[] = [
{
accessorKey: "amount",
header: () => <div className="text-right">Amount</div>,
cell: ({ row }) => {
const amount = parseFloat(row.getValue("amount"))
const formatted = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "USD",
}).format(amount)
return <div className="text-right font-medium">{formatted}</div>
},
},
]
您可以使用相同的方法来格式化其他单元格和页眉。
行操作
让我们在表格中添加