跳到主要内容

EditableTable

受控的行内可编辑表格。同一时间只有一行处于编辑状态;编辑、新增、删除行都只是对受控的 value 数组进行操作,并通过 onChange 输出结果。构建于底层的 Table 与 VEF 表单模块之上——不涉及任何查询或 mutation。

VEF 专属组件。 并非 Ant Design 的一部分。

何时使用

  • 需要行内编辑一个数组——例如表单中的明细行,或任何绑定到单一值的小型结构化列表——而不需要为每行单独进行查询/mutation 往返。
  • 需要为每一列提供只读(renderView)与编辑(renderEditor)两种渲染插槽,并通过 createEditableColumn 获得类型安全的字段校验器。
  • 当数据行来自带分页的远程查询、且每行拥有自己的 API 调用时,应改用 Crud / ProTable

基础用法

import { createEditableColumn, EditableTable } from '@vef-framework-react/components';
import type { EditableColumn } from '@vef-framework-react/components';
import { useState } from 'react';

interface Row {
id: string;
name: string;
age: number;
}

const columns: Array<EditableColumn<Row>> = [
createEditableColumn<Row>('name', {
title: 'Name',
validators: { onChange: ({ value }) => (value ? undefined : 'Name required') },
renderEditor: (field) => <field.Input noWrapper />,
}),
createEditableColumn<Row>('age', {
title: 'Age',
renderView: (value) => `${value} yo`,
renderEditor: (field) => <field.InputNumber noWrapper />,
}),
];

export default function Demo() {
const [rows, setRows] = useState<Row[]>([
{ id: '1', name: 'Edward', age: 32 },
{ id: '2', name: 'Helena', age: 28 },
]);

return (
<EditableTable<Row>
columns={columns}
rowKey="id"
value={rows}
onChange={setRows}
/>
);
}

新增与删除行

<EditableTable<Row>
columns={columns}
rowKey="id"
value={rows}
creatable
canDelete
createRecord={() => ({ name: '', age: 18 })}
onChange={setRows}
/>

canEditcanDelete 也接受逐行的判断函数:canDelete={(row) => row.age >= 18}

额外的行操作

<EditableTable<Row>
columns={columns}
rowKey="id"
value={rows}
renderRowActions={(row) => <a onClick={() => console.log(row)}>View</a>}
onChange={setRows}
/>

操作列覆盖

追加的操作列默认使用固定的 160px 宽度(恰好容纳内置的两个操作按钮)。当 renderRowActions 增加了额外操作时,请把它加宽:

<EditableTable<Row>
columns={columns}
rowKey="id"
value={rows}
operationColumn={{ title: 'Actions', width: 220 }}
onChange={setRows}
/>

API

EditableTableProps<TRow>

Prop类型默认值说明
valueTRow[]必填受控的行数据
onChange(value: TRow[]) => void每次编辑/新增/删除时都会带上下一份数组触发
columnsArray<EditableColumn<TRow>>必填带有 renderView / renderEditor 插槽的列定义
rowKeyDeepKeys<TRow> | ((row: TRow) => string)"key"行标识:字段名或函数;为正在编辑的行提供稳定标识
canEditboolean | ((row: TRow) => boolean)true某行是否可以进入编辑模式
canDeleteboolean | ((row: TRow) => boolean)false某行是否可以被删除
creatableboolean在表格下方显示新增行按钮
createRecord() => Partial<TRow>新增行时生成默认值的工厂函数
renderRowActions(row: TRow, index: number) => ReactNode渲染在内置编辑/删除按钮之前的额外只读态操作
operationColumnEditableOperationColumnConfig操作列覆盖(标题/宽度/按钮文案)
sizeTableProps<TRow>["size"]表格密度,转发给底层表格
paginationTableProps<TRow>["pagination"]false客户端分页配置,转发给底层表格
localeTableProps<TRow>["locale"]表格文案覆盖(例如更紧凑的 emptyText),转发给底层表格

EditableColumn<TRow>

通过 createEditableColumn<TRow>(dataIndex, options) 构建——这是一个类型安全的工厂函数,会把 options 拆分为展示字段、两个渲染插槽,以及供编辑器使用的 <form.AppField> 选项(校验器、监听器等)。

字段类型说明
dataIndexDeepKeys<TRow>该列的数据 key;编辑时同时作为表单字段名
keystring稳定的列标识;默认等于 dataIndex
editableboolean该列是否参与编辑;默认为 true
titleReactNode列标题
width / minWidthLength列宽约束
align'left' | 'center' | 'right'单元格对齐方式
fixed'left' | 'right' | boolean固定列
ellipsisboolean | { showTitle }溢出文本截断
classNamestring单元格类名
renderView(value: unknown, row: TRow, index: number) => ReactNode只读展示插槽;未提供时回退为原始值
renderEditor(field: typeof fieldComponents, context: EditFieldContext<TRow>) => ReactNode编辑插槽;未提供时该列保持只读
(校验器、监听器等)createField 所接受的任意 <form.AppField> 选项,会转发给该行的草稿表单

renderEditorfield 参数与 createField 所用的字段组件字典相同(field.Inputfield.Select 等);context 携带 { row, index, rowKey }

EditableOperationColumnConfig

字段类型说明
titleReactNode操作列标题;默认为 "操作"
widthLength操作列宽度。默认固定为 160 px,足以容纳内置的两个操作按钮——若不固定宽度,弹性布局的表格会把所有剩余空间都分给操作列。当 renderRowActions 增加了额外操作时请加宽
textsEditableRowActionsTexts内置行操作按钮的自定义文案

EditableRowActionsTexts

字段类型说明
editReactNode编辑按钮文案
saveReactNode保存按钮文案
cancelReactNode取消按钮文案
deleteReactNode删除按钮文案