数据表格以表格形式显示数据。
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';
数据表格需要一个 value 作为要显示的数据,并需要 Column 组件作为子组件进行表示。
<DataTable value={products} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
列可以通过编程方式创建。
<DataTable value={products} tableStyle={{ minWidth: '50rem' }}>
{columns.map((col, i) => (
<Column key={col.field} field={col.field} header={col.header} />
))}
</DataTable>
通过模板支持在 header、body 和 footer 部分的自定义内容。
<DataTable value={products} header={header} footer={footer} tableStyle={{ minWidth: '60rem' }}>
<Column field="name" header="Name"></Column>
<Column header="Image" body={imageBodyTemplate}></Column>
<Column field="price" header="Price" body={priceBodyTemplate}></Column>
<Column field="category" header="Category"></Column>
<Column field="rating" header="Reviews" body={ratingBodyTemplate}></Column>
<Column header="Status" body={statusBodyTemplate}></Column>
</DataTable>
除了常规表格外,还可以使用其他尺寸的替代方案。
<SelectButton value={size} onChange={(e) => setSize(e.value)} options={sizeOptions} />
<DataTable value={products} size={size} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
启用 showGridlines 将显示单元格之间的边框。
<DataTable value={products} showGridlines tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
当存在 stripedRows 属性时,将显示交替的行。
<DataTable value={products} stripedRows tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
通过添加 paginator 属性并定义每页 rows 来启用分页。
<DataTable value={customers} paginator rows={5} rowsPerPageOptions={[5, 10, 25, 50]} tableStyle={{ minWidth: '50rem' }}>
<Column field="name" header="Name" style={{ width: '25%' }}></Column>
<Column field="country.name" header="Country" style={{ width: '25%' }}></Column>
<Column field="company" header="Company" style={{ width: '25%' }}></Column>
<Column field="representative.name" header="Representative" style={{ width: '25%' }}></Column>
</DataTable>
分页器 UI 使用 paginatorTemplate 属性进行自定义。 每个元素还可以使用您自己的 UI 进一步自定义以替换默认 UI,有关高级自定义选项的更多信息,请参阅 分页器 组件。
<DataTable value={customers} paginator rows={5} rowsPerPageOptions={[5, 10, 25, 50]} tableStyle={{ minWidth: '50rem' }}
paginatorTemplate="RowsPerPageDropdown FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"
currentPageReportTemplate="{first} to {last} of {totalRecords}" paginatorLeft={paginatorLeft} paginatorRight={paginatorRight}>
<Column field="name" header="Name" style={{ width: '25%' }}></Column>
<Column field="country.name" header="Country" style={{ width: '25%' }}></Column>
<Column field="company" header="Company" style={{ width: '25%' }}></Column>
<Column field="representative.name" header="Representative" style={{ width: '25%' }}></Column>
</DataTable>
通过添加 sortable 属性启用列排序。
<DataTable value={products} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code" sortable style={{ width: '25%' }}></Column>
<Column field="name" header="Name" sortable style={{ width: '25%' }}></Column>
<Column field="category" header="Category" sortable style={{ width: '25%' }}></Column>
<Column field="quantity" header="Quantity" sortable style={{ width: '25%' }}></Column>
</DataTable>
可以通过将 sortMode 定义为 multiple 来对多列进行排序。 此模式需要按住 metaKey(例如 ⌘)才能单击标题。
<DataTable value={products} sortMode="multiple" tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code" sortable style={{ width: '25%' }}></Column>
<Column field="name" header="Name" sortable style={{ width: '25%' }}></Column>
<Column field="category" header="Category" sortable style={{ width: '25%' }}></Column>
<Column field="quantity" header="Quantity" sortable style={{ width: '25%' }}></Column>
</DataTable>
定义默认的 sortField 和 sortOrder 会在单列排序中初始显示排序后的数据。 在 multiple 排序模式下,应改用 multiSortMeta 并提供 DataTableSortMeta 对象的数组。
<DataTable value={products} sortField="price" sortOrder={-1} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code" sortable style={{ width: '20%' }}></Column>
<Column field="name" header="Name" sortable style={{ width: '20%' }}></Column>
<Column field="price" header="Price" body={priceBodyTemplate} sortable style={{ width: '20%' }}></Column>
<Column field="category" header="Category" sortable style={{ width: '20%' }}></Column>
<Column field="quantity" header="Quantity" sortable style={{ width: '20%' }}></Column>
</DataTable>
当存在 removableSort 时,第三次单击会从列中删除排序。
<DataTable value={products} removableSort tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code" sortable style={{ width: '25%' }}></Column>
<Column field="name" header="Name" sortable style={{ width: '25%' }}></Column>
<Column field="category" header="Category" sortable style={{ width: '25%' }}></Column>
<Column field="quantity" header="Quantity" sortable style={{ width: '25%' }}></Column>
</DataTable>
通过定义引用 DataTableFilterMeta 实例的 filters 属性来启用数据筛选。 要筛选的每一列还需要启用 filter。 内置筛选元素是一个输入字段,并且使用 filterElement,可以使用您自己的 UI 自定义筛选。 当 filterDisplay 定义为 row 时,筛选元素将显示在单独的行中。
可选的全局筛选会根据绑定到 filters 对象的 global 键的单个值搜索数据。 要搜索的字段使用 globalFilterFields 定义。
<DataTable value={customers} paginator rows={10} dataKey="id" filters={filters} filterDisplay="row" loading={loading}
globalFilterFields={['name', 'country.name', 'representative.name', 'status']} header={header} emptyMessage="No customers found.">
<Column field="name" header="Name" filter filterPlaceholder="Search by name" style={{ minWidth: '12rem' }} />
<Column header="Country" filterField="country.name" style={{ minWidth: '12rem' }} body={countryBodyTemplate} filter filterPlaceholder="Search by country" />
<Column header="Agent" filterField="representative" showFilterMenu={false} filterMenuStyle={{ width: '14rem' }} style={{ minWidth: '14rem' }}
body={representativeBodyTemplate} filter filterElement={representativeRowFilterTemplate} />
<Column field="status" header="Status" showFilterMenu={false} filterMenuStyle={{ width: '14rem' }} style={{ minWidth: '12rem' }} body={statusBodyTemplate} filter filterElement={statusRowFilterTemplate} />
<Column field="verified" header="Verified" dataType="boolean" style={{ minWidth: '6rem' }} body={verifiedBodyTemplate} filter filterElement={verifiedRowFilterTemplate} />
</DataTable>
当 filterDisplay 设置为 menu 时,将通过弹出窗口完成筛选,并支持多个约束和高级模板。
<DataTable value={customers} paginator showGridlines rows={10} loading={loading} dataKey="id"
filters={filters} globalFilterFields={['name', 'country.name', 'representative.name', 'balance', 'status']} header={header}
emptyMessage="No customers found." onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header="Name" filter filterPlaceholder="Search by name" style={{ minWidth: '12rem' }} />
<Column header="Country" filterField="country.name" style={{ minWidth: '12rem' }} body={countryBodyTemplate}
filter filterPlaceholder="Search by country" filterClear={filterClearTemplate}
filterApply={filterApplyTemplate} filterFooter={filterFooterTemplate} />
<Column header="Agent" filterField="representative" showFilterMatchModes={false} filterMenuStyle={{ width: '14rem' }} style={{ minWidth: '14rem' }}
body={representativeBodyTemplate} filter filterElement={representativeFilterTemplate} />
<Column header="Date" filterField="date" dataType="date" style={{ minWidth: '10rem' }} body={dateBodyTemplate} filter filterElement={dateFilterTemplate} />
<Column header="Balance" filterField="balance" dataType="numeric" style={{ minWidth: '10rem' }} body={balanceBodyTemplate} filter filterElement={balanceFilterTemplate} />
<Column field="status" header="Status" filterMenuStyle={{ width: '14rem' }} style={{ minWidth: '12rem' }} body={statusBodyTemplate} filter filterElement={statusFilterTemplate} />
<Column field="activity" header="Activity" showFilterMatchModes={false} style={{ minWidth: '12rem' }} body={activityBodyTemplate} filter filterElement={activityFilterTemplate} />
<Column field="verified" header="Verified" dataType="boolean" bodyClassName="text-center" style={{ minWidth: '8rem' }} body={verifiedBodyTemplate} filter filterElement={verifiedFilterTemplate} />
</DataTable>
通过使用 FilterService.register 定义筛选函数来启用自定义筛选,其中规则参数必须为 "custom_[field]"。 此示例中的“Activity”字段允许通过两个值的范围进行自定义筛选。
// The rule argument should be a string in the format "custom_[field]".
FilterService.register('custom_activity', (value, filters) => {
const [from, to] = filters ?? [null, null];
if (from === null && to === null) return true;
if (from !== null && to === null) return from <= value;
if (from === null && to !== null) return value <= to;
return from <= value && value <= to;
});
<DataTable value={customers} paginator rows={10} dataKey="id" filters={filters} filterDisplay="row" loading={loading}
globalFilterFields={['name', 'country.name', 'representative.name', 'status']} header={header} emptyMessage="No customers found.">
<Column field="name" header="Name" filter filterPlaceholder="Search by name" style={{ minWidth: '12rem' }} />
<Column header="Country" filterField="country.name" style={{ minWidth: '12rem' }} body={countryBodyTemplate} filter filterPlaceholder="Search by country" />
<Column header="Agent" filterField="representative" showFilterMenu={false} filterMenuStyle={{ width: '14rem' }} style={{ minWidth: '14rem' }}
body={representativeBodyTemplate} filter filterElement={representativeRowFilterTemplate} />
<Column header="Activity(Custom Filter)" field="activity" showFilterMenu={false} showClearButton={false} style={{ minWidth: '14rem' }} filter filterElement={activityRowFilterTemplate} />
<Column field="status" header="Status" showFilterMenu={false} filterMenuStyle={{ width: '14rem' }} style={{ minWidth: '12rem' }} body={statusBodyTemplate} filter filterElement={statusRowFilterTemplate} />
<Column field="verified" header="Verified" dataType="boolean" style={{ minWidth: '6rem' }} body={verifiedBodyTemplate} filter filterElement={verifiedRowFilterTemplate} />
</DataTable>
通过将 selectionMode 定义为 single 以及使用 selection 和 onSelectionChange 属性的值绑定来启用单行选择。 如果可用,建议使用 dataKey 提供行的唯一标识符以优化性能。
默认情况下,需要按住 metaKey(例如 ⌘)才能取消选择行,但是可以通过禁用 metaKeySelection 属性来配置此行为。 在启用触摸的设备中,此选项不起作用,行为与将其设置为 false 相同。
<InputSwitch checked={metaKey} onChange={(e) => setMetaKey(e.value)} />
<DataTable value={products} selectionMode="single" selection={selectedProduct}
onSelectionChange={(e) => setSelectedProduct(e.value)} dataKey="id" metaKeySelection={metaKey} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
通过将 selectionMode 设置为 multiple,可以选择多行。 在多选模式下,默认情况下,需要按住 metaKey(例如 ⌘)才能添加到现有选择中,但是可以通过禁用 metaKeySelection 属性来配置此行为。 请注意,在启用触摸的设备中,数据表格始终忽略 metaKey。
此外,当存在 dragSelection 时,可以使用拖动选择多行。
<InputSwitch checked={metaKey} onChange={(e) => setMetaKey(e.value)} />
<DataTable value={products} selectionMode="multiple" selection={selectedProducts} onSelectionChange={(e) => setSelectedProducts(e.value)}
dataKey="id" metaKeySelection={metaKey} dragSelection tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
在列上将 selectionMode 指定为 single,会在该列内显示一个单选按钮用于选择。 默认情况下,单击行也会触发选择,将数据表格的 selectionMode 设置为 radiobutton 以仅使用单选按钮触发选择。
<InputSwitch checked={rowClick} onChange={(e) => setRowClick(e.value)} />
<DataTable value={products} selectionMode={rowClick ? null : 'radiobutton'} selection={selectedProduct} onSelectionChange={(e) => setSelectedProduct(e.value)} dataKey="id" tableStyle={{ minWidth: '50rem' }}>
<Column selectionMode="single" headerStyle={{ width: '3rem' }}></Column>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
在列上将 selectionMode 指定为 multiple,会在该列内显示一个复选框用于选择。 默认情况下,单击行也会触发选择,将数据表格的 selectionMode 设置为 checkbox 以仅使用复选框触发选择。
默认情况下,标题复选框会切换整个数据集的选择状态,当启用分页器时,您可以添加 selectionPageOnly 以仅控制可见行的选择。
<InputSwitch checked={rowClick} onChange={(e) => setRowClick(e.value)} />
<DataTable value={products} selectionMode={rowClick ? null : 'checkbox'} selection={selectedProducts} onSelectionChange={(e) => setSelectedProducts(e.value)} dataKey="id" tableStyle={{ minWidth: '50rem' }}>
<Column selectionMode="multiple" headerStyle={{ width: '3rem' }}></Column>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
数据表格提供 onRowSelect 和 onRowUnselect 事件来侦听选择事件。
<DataTable value={products} selectionMode="single" selection={selectedProduct} onSelectionChange={(e) => setSelectedProduct(e.value)} dataKey="id"
onRowSelect={onRowSelect} onRowUnselect={onRowUnselect} metaKeySelection={false} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
如果 isDataSelectable 返回 false,则可以从选择中排除某些行。
<DataTable value={products} selectionMode="single" selection={selectedProduct} onSelectionChange={(e) => setSelectedProduct(e.value)} dataKey="id"
isDataSelectable={isRowSelectable} rowClassName={rowClassName} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
通过添加 cellSelection,将 selectionMode 定义为 single 以及使用 selection 和 onSelectionChange 属性的值绑定来启用单单元格选择。 选择的类型将是 DataTableCellSelection,它提供有关单元格的信息,例如 cellIndex 和 rowIndex。
默认情况下,需要按住 metaKey(例如 ⌘)才能取消选择单元格,但是可以通过禁用 metaKeySelection 属性来配置此行为。 在启用触摸的设备中,此选项不起作用,行为与将其设置为 false 相同。
<InputSwitch checked={metaKey} onChange={(e) => setMetaKey(e.value)} />
<DataTable value={products} cellSelection selectionMode="single" selection={selectedCell}
onSelectionChange={(e) => setSelectedCell(e.value)} metaKeySelection={metaKey} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
通过将 selectionMode 设置为 multiple,可以选择多个单元格。 在多选模式下,默认情况下,需要按住 metaKey(例如 ⌘)才能添加到现有选择中,但是可以通过禁用 metaKeySelection 属性来配置此行为。 请注意,在启用触摸的设备中,数据表格始终忽略 metaKey。
此外,当存在 dragSelection 时,可以使用拖动选择多个单元格。
<InputSwitch checked={metaKey} onChange={(e) => setMetaKey(e.value)} />
<DataTable value={products} cellSelection selectionMode="multiple" selection={selectedCells}
onSelectionChange={(e) => setSelectedCells(e.value)}
metaKeySelection={metaKey} dragSelection tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
DataTable 提供了 onCellSelect 和 onCellUnselect 事件来监听选择事件。
<Toast ref={toast} />
<DataTable value={products} cellSelection selectionMode="single" selection={selectedCell}
onSelectionChange={(e) => setSelectedCell(e.value)} metaKeySelection={false}
onCellSelect={onCellSelect} onCellUnselect={onCellUnselect} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
如果 isDataSelectable 返回 false,则可以排除某些单元格不被选择。
<InputSwitch checked={metaKey} onChange={(e) => setMetaKey(e.value)} />
<DataTable value={products} cellSelection selectionMode="single" selection={selectedCell}
onSelectionChange={(e) => setSelectedCell(e.value)} metaKeySelection={metaKey}
isDataSelectable={isCellSelectable} cellClassName={cellClassName} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
行展开通过 expandedRows 和 onRowToggle 属性控制。具有展开元素的列需要启用 expander 属性。可选的 onRowExpand 和 onRowCollapse事件可用作回调。
展开的行可以是行数据的数组,或者当存在 dataKey 时,一个对象,其键是指向行数据标识符的字符串,而值是表示展开状态的布尔值,例如: {'1004': true}。 对于大量数据,dataKey 替代方案性能更高。
<DataTable value={products} expandedRows={expandedRows} onRowToggle={(e) => setExpandedRows(e.data)}
onRowExpand={onRowExpand} onRowCollapse={onRowCollapse} rowExpansionTemplate={rowExpansionTemplate}
dataKey="id" header={header} tableStyle={{ minWidth: '60rem' }}>
<Column expander={allowExpansion} style={{ width: '5rem' }} />
<Column field="name" header="Name" sortable />
<Column header="Image" body={imageBodyTemplate} />
<Column field="price" header="Price" sortable body={priceBodyTemplate} />
<Column field="category" header="Category" sortable />
<Column field="rating" header="Reviews" sortable body={ratingBodyTemplate} />
<Column field="inventoryStatus" header="Status" sortable body={statusBodyTemplate} />
</DataTable>
通过将 editMode 设置为 cell,使用列的 editor 属性定义输入元素,并实现 onCellEditComplete 来更新状态,可以启用单元格编辑。
<DataTable value={products} editMode="cell" tableStyle={{ minWidth: '50rem' }}>
{columns.map(({ field, header }) => {
return <Column key={field} field={field} header={header}
style={{ width: '25%' }} body={field === 'price' && priceBodyTemplate}
editor={(options) => cellEditor(options)} onCellEditComplete={onCellEditComplete} />;
})}
</DataTable>
通过将 editMode 设置为 row 来配置行编辑。与单元格编辑模式类似,必须使用列的 editor 属性定义输入元素,并实现 onRowEditComplete 来更新状态。控制编辑状态的列应该应用 rowEditor 属性。
<DataTable value={products} editMode="row" dataKey="id" onRowEditComplete={onRowEditComplete} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code" editor={(options) => textEditor(options)} style={{ width: '20%' }}></Column>
<Column field="name" header="Name" editor={(options) => textEditor(options)} style={{ width: '20%' }}></Column>
<Column field="inventoryStatus" header="Status" body={statusBodyTemplate} editor={(options) => statusEditor(options)} style={{ width: '20%' }}></Column>
<Column field="price" header="Price" body={priceBodyTemplate} editor={(options) => priceEditor(options)} style={{ width: '20%' }}></Column>
<Column rowEditor={allowEdit} headerStyle={{ width: '10%', minWidth: '8rem' }} bodyStyle={{ textAlign: 'center' }}></Column>
</DataTable>
懒加载模式对于处理大型数据集非常方便,而不是加载整个数据,每次发生 分页、排序 和 过滤 时,都会通过调用相应的回调来加载少量数据块。下面的示例模拟使用内存列表和超时从远程数据源懒加载数据,以模拟网络连接。
启用 lazy 属性并将逻辑行数分配给 totalRecords,通过执行投影查询是实现的关键要素,以便分页器显示 UI,假设实际上存在 totalRecords 大小的记录,尽管实际上它们不在页面上,只存在当前页面上显示的记录。
请注意,懒加载模式下 复选框选择 的实现需要手动处理,如本示例所示,因为 DataTable 无法了解整个数据集。
名称 | 国家 | 公司 | 代表 | |
---|---|---|---|---|
<DataTable value={customers} lazy filterDisplay="row" dataKey="id" paginator
first={lazyState.first} rows={10} totalRecords={totalRecords} onPage={onPage}
onSort={onSort} sortField={lazyState.sortField} sortOrder={lazyState.sortOrder}
onFilter={onFilter} filters={lazyState.filters} loading={loading} tableStyle={{ minWidth: '75rem' }}
selection={selectedCustomers} onSelectionChange={onSelectionChange} selectAll={selectAll} onSelectAllChange={onSelectAllChange}>
<Column selectionMode="multiple" headerStyle={{ width: '3rem' }} />
<Column field="name" header="Name" sortable filter filterPlaceholder="Search" />
<Column field="country.name" sortable header="Country" filterField="country.name" body={countryBodyTemplate} filter filterPlaceholder="Search" />
<Column field="company" sortable filter header="Company" filterPlaceholder="Search" />
<Column field="representative.name" header="Representative" body={representativeBodyTemplate} filter filterPlaceholder="Search" />
</DataTable>
添加 scrollable 属性以及数据视口的 scrollHeight 可以启用具有固定标题的垂直滚动。
<DataTable value={customers} scrollable scrollHeight="400px" style={{ minWidth: '50rem' }}>
<Column field="name" header="Name"></Column>
<Column field="country.name" header="Country"></Column>
<Column field="representative.name" header="Representative"></Column>
<Column field="company" header="Company"></Column>
</DataTable>
弹性滚动功能使可滚动视口部分变为动态,而不是固定值,使其可以相对于表格的父大小增长或缩小。单击下面的按钮以显示一个可最大化的对话框,其中数据视口会根据大小变化自行调整。
<Button label="Show" icon="pi pi-external-link" onClick={() => setDialogVisible(true)} />
<Dialog header="Flex Scroll" visible={dialogVisible} style={{ width: '75vw' }} maximizable
modal contentStyle={{ height: '300px' }} onHide={() => setDialogVisible(false)} footer={dialogFooterTemplate}>
<DataTable value={customers} scrollable scrollHeight="flex" tableStyle={{ minWidth: '50rem' }}>
<Column field="name" header="Name"></Column>
<Column field="country.name" header="Country"></Column>
<Column field="representative.name" header="Representative"></Column>
<Column field="company" header="Company"></Column>
</DataTable>
</Dialog>
当表格宽度超过父宽度时,会显示水平滚动条。
<DataTable value={customers} scrollable scrollHeight="400px">
<Column field="id" header="Id" footer="Id" style={{ minWidth: '100px' }}></Column>
<Column field="name" header="Name" footer="Name" style={{ minWidth: '200px' }}></Column>
<Column field="country.name" header="Country" footer="Country" style={{ minWidth: '200px' }}></Column>
<Column field="date" header="Date" footer="Date" style={{ minWidth: '200px' }}></Column>
<Column field="balance" header="Balance" footer="Balance" body={balanceTemplate} style={{ minWidth: '200px' }}></Column>
<Column field="company" header="Company" footer="Company" style={{ minWidth: '200px' }}></Column>
<Column field="status" header="Status" footer="Status" style={{ minWidth: '200px' }}></Column>
<Column field="activity" header="Activity" footer="Activity" style={{ minWidth: '200px' }}></Column>
<Column field="representative.name" header="Representative" footer="Representative" style={{ minWidth: '200px' }}></Column>
</DataTable>
通过启用 frozenValue 属性,可以在滚动过程中固定行。
<DataTable value={customers} frozenValue={lockedCustomers} scrollable scrollHeight="400px" tableStyle={{ minWidth: '50rem' }}>
<Column field="name" header="Name"></Column>
<Column field="country.name" header="Country"></Column>
<Column field="representative.name" header="Representative"></Column>
<Column field="status" header="Status"></Column>
<Column style={{ flex: '0 0 4rem' }} body={lockTemplate}></Column>
</DataTable>
通过启用 frozen 属性,可以在水平滚动期间固定列。位置由 alignFrozen 定义,可以是 left 或 right。
<ToggleButton checked={balanceFrozen} onChange={(e) => setBalanceFrozen(e.value)}
onIcon="pi pi-lock" offIcon="pi pi-lock-open" onLabel="Balance" offLabel="Balance" />
<DataTable value={customers} scrollable scrollHeight="400px" className="mt-4">
<Column field="name" header="Name" style={{ minWidth: '200px' }} frozen className="font-bold"></Column>
<Column field="id" header="Id" style={{ minWidth: '100px' }}></Column>
<Column field="name" header="Name" style={{ minWidth: '200px' }}></Column>
<Column field="country.name" header="Country" style={{ minWidth: '200px' }}></Column>
<Column field="date" header="Date" style={{ minWidth: '200px' }}></Column>
<Column field="company" header="Company" style={{ minWidth: '200px' }}></Column>
<Column field="status" header="Status" style={{ minWidth: '200px' }}></Column>
<Column field="activity" header="Activity" style={{ minWidth: '200px' }}></Column>
<Column field="representative.name" header="Representative" style={{ minWidth: '200px' }}></Column>
<Column field="balance" header="Balance" body={balanceTemplate} style={{ minWidth: '200px' }} alignFrozen="right" frozen={balanceFrozen}></Column>
</DataTable>
虚拟滚动是渲染大量数据的一种有效方法。用法类似于常规滚动,但添加了 virtualScrollerOptions 属性来定义固定的 itemSize。在内部, VirtualScroller 组件被使用,因此请参阅 VirtualScroller 的 API 以获取有关可用选项的更多信息。
在此示例中,表格渲染了 100000 个预加载的记录。
<DataTable value={cars} scrollable scrollHeight="400px" virtualScrollerOptions={{ itemSize: 46 }} tableStyle={{ minWidth: '50rem' }}>
<Column field="id" header="Id" style={{ width: '20%' }}></Column>
<Column field="vin" header="Vin" style={{ width: '20%' }}></Column>
<Column field="year" header="Year" style={{ width: '20%' }}></Column>
<Column field="brand" header="Brand" style={{ width: '20%' }}></Column>
<Column field="color" header="Color" style={{ width: '20%' }}></Column>
</DataTable>
当通过 virtualScrollerOptions 启用懒加载时,数据会在滚动期间按需获取,而不是预加载。
在下面的示例中,使用内存列表和超时来模拟从远程数据源获取。virtualCars 是一个空数组,在滚动时填充。
<DataTable value={virtualCars} scrollable scrollHeight="400px"
virtualScrollerOptions={{ lazy: true, onLazyLoad: loadCarsLazy, itemSize: 46, delay: 200, showLoader: true, loading: lazyLoading, loadingTemplate }}
tableStyle={{ minWidth: '50rem' }}>
<Column field="id" header="Id" style={{ width: '20%' }}></Column>
<Column field="vin" header="Vin" style={{ width: '20%' }}></Column>
<Column field="year" header="Year" style={{ width: '20%' }}></Column>
<Column field="brand" header="Brand" style={{ width: '20%' }}></Column>
<Column field="color" header="Color" style={{ width: '20%' }}></Column>
</DataTable>
可以使用 Row 组件对列进行分组,并且可以使用 headerColumnGroup、footerColumnGroup 属性在页眉和页脚显示分组。要跨越的单元格和行数使用 列的 colSpan 和 rowSpan 属性定义。
<DataTable value={sales} headerColumnGroup={headerGroup} footerColumnGroup={footerGroup} tableStyle={{ minWidth: '50rem' }}>
<Column field="product" />
<Column field="lastYearSale" body={lastYearSaleBodyTemplate} />
<Column field="thisYearSale" body={thisYearSaleBodyTemplate} />
<Column field="lastYearProfit" body={lastYearProfitBodyTemplate} />
<Column field="thisYearProfit" body={thisYearProfitBodyTemplate} />
</DataTable>
行使用 groupRowsBy 属性进行分组。当 rowGroupMode 设置为 subheader 时,可以为每个组显示页眉和页脚。组页眉的内容通过 rowGroupHeaderTemplate 提供,而页脚的内容通过 rowGroupFooterTemplate 提供。
<DataTable value={customers} rowGroupMode="subheader" groupRowsBy="representative.name" sortMode="single" sortField="representative.name"
sortOrder={1} scrollable scrollHeight="400px" rowGroupHeaderTemplate={headerTemplate} rowGroupFooterTemplate={footerTemplate} tableStyle={{ minWidth: '50rem' }}>
<Column field="name" header="Name" style={{ minWidth: '200px' }}></Column>
<Column field="country" header="Country" body={countryBodyTemplate} style={{ minWidth: '200px' }}></Column>
<Column field="company" header="Company" style={{ minWidth: '200px' }}></Column>
<Column field="status" header="Status" body={statusBodyTemplate} style={{ minWidth: '200px' }}></Column>
<Column field="date" header="Date" style={{ minWidth: '200px' }}></Column>
</DataTable>
当基于子标题的行分组中存在 expandableRowGroups 时,可以展开和折叠组。展开状态使用 expandedRows 和 onRowToggle 属性控制。
<DataTable value={customers} rowGroupMode="subheader" groupRowsBy="representative.name"
sortMode="single" sortField="representative.name" sortOrder={1}
expandableRowGroups expandedRows={expandedRows} onRowToggle={(e) => setExpandedRows(e.data)}
rowGroupHeaderTemplate={headerTemplate} rowGroupFooterTemplate={footerTemplate} tableStyle={{ minWidth: '50rem' }}>
<Column field="name" header="Name" style={{ width: '20%' }}></Column>
<Column field="country" header="Country" body={countryBodyTemplate} style={{ width: '20%' }}></Column>
<Column field="company" header="Company" style={{ width: '20%' }}></Column>
<Column field="status" header="Status" body={statusBodyTemplate} style={{ width: '20%' }}></Column>
<Column field="date" header="Date" style={{ width: '20%' }}></Column>
</DataTable>
当 rowGroupMode 配置为 rowspan 时,分组列将跨越多行。
<DataTable value={customers} rowGroupMode="rowspan" groupRowsBy="representative.name"
sortMode="single" sortField="representative.name" sortOrder={1} tableStyle={{ minWidth: '50rem' }}>
<Column header="#" headerStyle={{ width: '3rem' }} body={(data, options) => options.rowIndex + 1}></Column>
<Column field="representative.name" header="Representative" body={representativeBodyTemplate} style={{ minWidth: '200px' }}></Column>
<Column field="name" header="Name" style={{ minWidth: '200px' }}></Column>
<Column field="country" header="Country" body={countryBodyTemplate} style={{ minWidth: '150px' }}></Column>
<Column field="company" header="Company" style={{ minWidth: '200px' }}></Column>
<Column field="status" header="Status" body={statusBodyTemplate} style={{ minWidth: '100px' }}></Column>
<Column field="date" header="Date" style={{ minWidth: '100px' }}></Column>
</DataTable>
可以根据条件设置特定行和单元格的样式。rowClassName 接收行数据作为参数,以返回行的样式类,而单元格使用 body 模板进行自定义。
<DataTable value={products} rowClassName={rowClass} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity" body={stockBodyTemplate}></Column>
</DataTable>
启用 resizableColumns 后,可以使用拖放来调整列的大小。默认的调整大小模式为 fit,不会更改表格的整体宽度。
<DataTable value={products} resizableColumns showGridlines tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
将 columnResizeMode 设置为 expand 也会更改表格的宽度。
<DataTable value={products} columnResizeMode="expand" resizableColumns showGridlines tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
可以使用拖放来更改列和行的顺序。通过添加 reorderableColumns 属性来配置列的重新排序。
类似地,添加 reorderableRows 属性可以启用可拖动的行。对于拖动手柄,列需要具有 rowReorder 属性,并且需要 onRowReorder 回调来控制重新排序完成后行的状态。
<DataTable value={products} reorderableColumns reorderableRows onRowReorder={(e) => setProducts(e.value)} tableStyle={{ minWidth: '50rem' }}>
<Column rowReorder style={{ width: '3rem' }} />
{dynamicColumns}
</DataTable>
可以使用动态列来实现基于条件的列可见性,在此示例中,使用 MultiSelect 来管理可见列。
<DataTable value={products} header={header} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code" />
{visibleColumns.map((col) => (
<Column key={col.field} field={col.field} header={col.header} />
))}
</DataTable>
CSV 导出是一项内置功能,在此示例中,还可以使用诸如 jsPDF 和 xlsx 之类的第三方库进行 PDF 和 XLS 导出。
<Button type="button" icon="pi pi-file" rounded onClick={() => exportCSV(false)} data-pr-tooltip="CSV" />
<Button type="button" icon="pi pi-file-excel" severity="success" rounded onClick={exportExcel} data-pr-tooltip="XLS" />
<Button type="button" icon="pi pi-file-pdf" severity="warning" rounded onClick={exportPdf} data-pr-tooltip="PDF" />
<DataTable ref={dt} value={products} header={header} tableStyle={{ minWidth: '50rem' }}>
{cols.map((col, index) => (
<Column key={index} field={col.field} header={col.header} />
))}
</DataTable>
DataTable 使用 onContextMenu 事件与 ContextMenu 进行了独家集成,以在右键单击时打开菜单,同时使用 contextMenuSelection 和 onContextMenuSelectionChange 属性来控制通过菜单进行的选择。
<Toast ref={toast} />
<ContextMenu model={menuModel} ref={cm} onHide={() => setSelectedProduct(null)} />
<DataTable value={products} onContextMenu={(e) => cm.current.show(e.originalEvent)}
contextMenuSelection={selectedProduct} onContextMenuSelectionChange={(e) => setSelectedProduct(e.value)} tableStyle={{ minWidth: '50rem' }}>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="price" header="Price" body={priceBodyTemplate} />
</DataTable>
有状态表格允许将诸如页面、排序和过滤之类的状态保存在本地存储或会话存储中,以便再次访问该页面时,表格将使用上次的设置来渲染数据。
更改表格的状态,例如分页,离开并再次返回此表格以测试此功能,该设置通过 stateStorage 属性设置为 session,以便表格在浏览器关闭之前保留状态。另一种选择是 local,指代 localStorage 以延长生命周期。
<DataTable value={customers} paginator rows={5} header={header} filters={filters} onFilter={(e) => setFilters(e.filters)}
selection={selectedCustomer} onSelectionChange={(e) => setSelectedCustomer(e.value)} selectionMode="single" dataKey="id"
stateStorage="session" stateKey="dt-state-demo-local" emptyMessage="No customers found." tableStyle={{ minWidth: '50rem' }}>
<Column field="name" header="Name" sortable filter filterPlaceholder="Search" style={{ width: '25%' }}></Column>
<Column header="Country" body={countryBodyTemplate} sortable sortField="country.name" filter filterField="country.name" filterPlaceholder="Search" style={{ width: '25%' }}></Column>
<Column header="Agent" body={representativeBodyTemplate} sortable sortField="representative.name" filter filterField="representative"
showFilterMatchModes={false} filterElement={representativeFilterTemplate} filterMenuStyle={{ width: '14rem' }} style={{ width: '25%' }} ></Column>
<Column field="status" header="Status" body={statusBodyTemplate} sortable filter filterElement={statusFilterTemplate} filterMenuStyle={{ width: '14rem' }} style={{ width: '25%' }}></Column>
</DataTable>
具有选择、分页、过滤、排序和模板的 DataTable。
<DataTable value={customers} paginator header={header} rows={10}
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
rowsPerPageOptions={[10, 25, 50]} dataKey="id" selectionMode="checkbox" selection={selectedCustomers} onSelectionChange={(e) => setSelectedCustomers(e.value)}
filters={filters} filterDisplay="menu" globalFilterFields={['name', 'country.name', 'representative.name', 'balance', 'status']}
emptyMessage="No customers found." currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries">
<Column selectionMode="multiple" headerStyle={{ width: '3rem' }}></Column>
<Column field="name" header="Name" sortable filter filterPlaceholder="Search by name" style={{ minWidth: '14rem' }} />
<Column field="country.name" header="Country" sortable filterField="country.name" style={{ minWidth: '14rem' }} body={countryBodyTemplate} filter filterPlaceholder="Search by country" />
<Column header="Agent" sortable sortField="representative.name" filterField="representative" showFilterMatchModes={false} filterMenuStyle={{ width: '14rem' }}
style={{ minWidth: '14rem' }} body={representativeBodyTemplate} filter filterElement={representativeFilterTemplate} />
<Column field="date" header="Date" sortable filterField="date" dataType="date" style={{ minWidth: '12rem' }} body={dateBodyTemplate} filter filterElement={dateFilterTemplate} />
<Column field="balance" header="Balance" sortable dataType="numeric" style={{ minWidth: '12rem' }} body={balanceBodyTemplate} filter filterElement={balanceFilterTemplate} />
<Column field="status" header="Status" sortable filterMenuStyle={{ width: '14rem' }} style={{ minWidth: '12rem' }} body={statusBodyTemplate} filter filterElement={statusFilterTemplate} />
<Column field="activity" header="Activity" sortable showFilterMatchModes={false} style={{ minWidth: '12rem' }} body={activityBodyTemplate} filter filterElement={activityFilterTemplate} />
<Column headerStyle={{ width: '5rem', textAlign: 'center' }} bodyStyle={{ textAlign: 'center', overflow: 'visible' }} body={actionBodyTemplate} />
</DataTable>
带有对话框的 CRUD 实现示例。
<Toolbar className="mb-4" left={leftToolbarTemplate} right={rightToolbarTemplate}></Toolbar>
<DataTable ref={dt} value={products} selection={selectedProducts} onSelectionChange={(e) => setSelectedProducts(e.value)}
dataKey="id" paginator rows={10} rowsPerPageOptions={[5, 10, 25]}
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products" globalFilter={globalFilter} header={header}>
<Column selectionMode="multiple" exportable={false}></Column>
<Column field="code" header="Code" sortable style={{ minWidth: '12rem' }}></Column>
<Column field="name" header="Name" sortable style={{ minWidth: '16rem' }}></Column>
<Column field="image" header="Image" body={imageBodyTemplate}></Column>
<Column field="price" header="Price" body={priceBodyTemplate} sortable style={{ minWidth: '8rem' }}></Column>
<Column field="category" header="Category" sortable style={{ minWidth: '10rem' }}></Column>
<Column field="rating" header="Reviews" body={ratingBodyTemplate} sortable style={{ minWidth: '12rem' }}></Column>
<Column field="inventoryStatus" header="Status" body={statusBodyTemplate} sortable style={{ minWidth: '12rem' }}></Column>
<Column body={actionBodyTemplate} exportable={false} style={{ minWidth: '12rem' }}></Column>
</DataTable>
DataTable 使用 table 元素,可以使用 tableProps 选项扩展其属性。此属性允许传递 aria 角色和属性,例如 aria-label 和 aria-describedby,以定义阅读器的表格。表格的默认角色是 table。页眉、正文和页脚元素使用 rowgroup,行使用 row 角色,标题单元格具有 columnheader,正文单元格使用 cell 角色。可排序的标题利用 aria-sort 属性,该属性设置为“ascending”或“descending”。
用于行选择的内置复选框和单选按钮组件分别使用 checkbox 和 radiobutton 角色,并带有 aria-checked 状态属性。用于描述它们的标签从本地化 API 的 aria.selectRow 和 aria.unselectRow 属性中检索。类似地,标题复选框使用 selectAll 和 unselectAll 键。当选择某一行时,该行的 aria-selected 将设置为 true。
用于展开或折叠行的元素是一个带有 aria-expanded 和 aria-controls 属性的 button。用于描述按钮的值从本地化 API 的 aria.expandRow 和 aria.collapseRow 属性派生。
过滤器菜单按钮使用 aria.showFilterMenu 和 aria.hideFilterMenu 属性作为 aria-label,此外还使用 aria-haspopup、aria-expanded 和 aria-controls 来定义按钮和叠加层之间的关系。弹出菜单具有 dialog 角色,并带有 aria-modal,因为焦点会保持在叠加层内。操作符下拉列表使用 aria.filterOperator 属性,过滤器约束下拉列表使用 aria.filterConstraint 属性。另一方面,用于添加规则的按钮则使用 aria.addRule和 aria.removeRule 属性。页脚按钮类似地使用 aria.clear 和 aria.apply 属性。如果使用模板化自定义组件,则可以使用 Column 组件的 filterInputProps 为内置过滤器组件定义 aria 标签,也可以定义自己的 aria 标签。
可编辑单元格使用自定义模板,因此如果需要,您需要手动管理 aria 角色和属性。行编辑器控件是带有 aria.editRow、aria.cancelEdit 和 aria.saveEdit 的按钮元素,用于 aria-label。
分页器是 DataTable 中使用的独立组件,有关辅助功能特性的更多信息,请参阅分页器。
DataTable 中用于诸如过滤器、行展开、编辑等情况的任何按钮元素都是可 Tab 键聚焦的,并且可以使用 空格 键和 Enter 键。
键 | 功能 |
---|---|
tab | 在标题之间移动。 |
enter | 对列进行排序。 |
space | 对列进行排序。 |
键 | 功能 |
---|---|
tab | 在弹出窗口内的元素之间移动。 |
escape | 隐藏弹出窗口。 |
键 | 功能 |
---|---|
tab | 将焦点移动到第一个选定的行,如果没有,则第一个行接收焦点。 |
上箭头 | 将焦点移动到上一行。 |
下箭头 | 将焦点移动到下一行。 |
enter | 根据 metaKeySelection 设置切换聚焦行的选择状态。 |
space | 根据 metaKeySelection 设置切换聚焦行的选择状态。 |
home | 将焦点移动到第一行。 |
end | 将焦点移动到最后一行。 |
shift + 下箭头 | 将焦点移动到下一行并切换选择状态。 |
shift + 上箭头 | 将焦点移动到上一行并切换选择状态。 |
shift + 空格 | 选择最近选择的行和聚焦行之间的行。 |
control + shift + home | 选择聚焦的行以及直到第一个选项的所有选项。 |
control + shift + end | 选择聚焦的行以及直到最后一个选项的所有选项。 |
control + a | 选择所有行。 |