数据表格

数据表格以表格形式显示数据。


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>
         

通过模板支持在 headerbodyfooter 部分的自定义内容。


<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>
         

定义默认的 sortFieldsortOrder 会在单列排序中初始显示排序后的数据。 在 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 以及使用 selectiononSelectionChange 属性的值绑定来启用单行选择。 如果可用,建议使用 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>
         

数据表格提供 onRowSelectonRowUnselect 事件来侦听选择事件。


<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 以及使用 selectiononSelectionChange 属性的值绑定来启用单单元格选择。 选择的类型将是 DataTableCellSelection,它提供有关单元格的信息,例如 cellIndexrowIndex

默认情况下,需要按住 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 提供了 onCellSelectonCellUnselect 事件来监听选择事件。


<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>
         

行展开通过 expandedRowsonRowToggle 属性控制。具有展开元素的列需要启用 expander 属性。可选的 onRowExpandonRowCollapse事件可用作回调。

展开的行可以是行数据的数组,或者当存在 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 定义,可以是 leftright


<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 组件对列进行分组,并且可以使用 headerColumnGroupfooterColumnGroup 属性在页眉和页脚显示分组。要跨越的单元格和行数使用 列的 colSpanrowSpan 属性定义。


<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 时,可以展开和折叠组。展开状态使用 expandedRowsonRowToggle 属性控制。


<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 导出是一项内置功能,在此示例中,还可以使用诸如 jsPDFxlsx 之类的第三方库进行 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 进行了独家集成,以在右键单击时打开菜单,同时使用 contextMenuSelectiononContextMenuSelectionChange 属性来控制通过菜单进行的选择。


<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-labelaria-describedby,以定义阅读器的表格。表格的默认角色是 table。页眉、正文和页脚元素使用 rowgroup,行使用 row 角色,标题单元格具有 columnheader,正文单元格使用 cell 角色。可排序的标题利用 aria-sort 属性,该属性设置为“ascending”或“descending”。

用于行选择的内置复选框和单选按钮组件分别使用 checkboxradiobutton 角色,并带有 aria-checked 状态属性。用于描述它们的标签从本地化 API 的 aria.selectRowaria.unselectRow 属性中检索。类似地,标题复选框使用 selectAllunselectAll 键。当选择某一行时,该行的 aria-selected 将设置为 true。

用于展开或折叠行的元素是一个带有 aria-expandedaria-controls 属性的 button。用于描述按钮的值从本地化 API 的 aria.expandRowaria.collapseRow 属性派生。

过滤器菜单按钮使用 aria.showFilterMenuaria.hideFilterMenu 属性作为 aria-label,此外还使用 aria-haspopuparia-expandedaria-controls 来定义按钮和叠加层之间的关系。弹出菜单具有 dialog 角色,并带有 aria-modal,因为焦点会保持在叠加层内。操作符下拉列表使用 aria.filterOperator 属性,过滤器约束下拉列表使用 aria.filterConstraint 属性。另一方面,用于添加规则的按钮则使用 aria.addRulearia.removeRule 属性。页脚按钮类似地使用 aria.cleararia.apply 属性。如果使用模板化自定义组件,则可以使用 Column 组件的 filterInputProps 为内置过滤器组件定义 aria 标签,也可以定义自己的 aria 标签。

可编辑单元格使用自定义模板,因此如果需要,您需要手动管理 aria 角色和属性。行编辑器控件是带有 aria.editRowaria.cancelEditaria.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选择所有行。