Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Table]支持行编辑功能 #1186

Merged
merged 4 commits into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 7 additions & 14 deletions examples/table/demos/editable-cell.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div>
<!-- 当前示例包含:输入框、单选、多选、日期 等场景 -->
<t-table row-key="key" :columns="columns" :data="data" bordered />
<t-table row-key="key" :columns="columns" :data="data" bordered @row-validate="onRowValidate" />
</div>
</template>

Expand All @@ -27,6 +27,10 @@ const initData = new Array(5).fill(null).map((_, i) => ({
const align = ref('left');
const data = ref([...initData]);

const onRowValidate = (params) => {
console.log('validate:', params);
};

const columns = computed(() => [
{
title: 'FirstName',
Expand Down Expand Up @@ -118,12 +122,10 @@ const columns = computed(() => [
{
title: 'Date',
colKey: 'createTime',
// props, 透传全部属性到 DatePicker 组件
edit: {
component: DatePicker,
props: {
mode: 'date',
},
// props, 透传全部属性到 DatePicker 组件
props: {},
// 除了点击非自身元素退出编辑态之外,还有哪些事件退出编辑态
abortEditOnEvent: ['onChange'],
onEdited: (context) => {
Expand All @@ -135,12 +137,3 @@ const columns = computed(() => [
},
]);
</script>
<style scoped>
.table-operations {
margin-bottom: 16px;
}

.table-operations > button {
margin-right: 8px;
}
</style>
219 changes: 219 additions & 0 deletions examples/table/demos/editable-row.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
<template>
<div class="t-table-demo__editable-row">
<!-- 当前示例包含:输入框、单选、多选、日期 等场景 -->
<t-table
ref="tableRef"
row-key="key"
:columns="columns"
:data="data"
:editable-row-keys="editableRowKeys"
vertical-align="top"
bordered
@row-edit="onRowEdit"
@row-validate="onRowValidate"
/>
</div>
</template>

<script setup lang="jsx">
import { ref, computed } from 'vue';
import { Input, Select, DatePicker, MessagePlugin, Button } from 'tdesign-vue-next';

const initData = new Array(5).fill(null).map((_, i) => ({
key: String(i + 1),
firstName: ['Eric', 'Gilberta', 'Heriberto', 'Lazarus', 'Zandra'][i % 4],
framework: ['Vue', 'React', 'Miniprogram', 'Flutter'][i % 4],
email: [
'espinke0@apache.org',
'gpurves1@issuu.com',
'hkment2@nsw.gov.au',
'lskures3@apache.org',
'zcroson5@virginia.edu',
][i % 4],
letters: [['A'], ['B', 'E'], ['C'], ['D', 'G', 'H']][i % 4],
createTime: ['2021-11-01', '2021-12-01', '2022-01-01', '2022-02-01', '2022-03-01'][i % 4],
}));

const tableRef = ref();
const align = ref('left');
const data = ref([...initData]);
const editableRowKeys = ref(['1']);
const currentSaveId = ref('');
// 保存变化过的行信息
const editMap = {};

const onEdit = (e) => {
const { id } = e.currentTarget.dataset;
if (!editableRowKeys.value.includes(id)) {
editableRowKeys.value.push(id);
}
};

// 更新 editableRowKeys
const updateEditState = (id) => {
const index = editableRowKeys.value.findIndex((t) => t === id);
editableRowKeys.value.splice(index, 1);
};

const onCancel = (e) => {
const { id } = e.currentTarget.dataset;
updateEditState(id);
};

const onSave = (e) => {
const { id } = e.currentTarget.dataset;
currentSaveId.value = id;
// 触发内部校验,而后在 onRowValidate 中接收异步校验结果
tableRef.value.validateRowDate(id);
};

const onRowValidate = (params) => {
console.log('validate:', params);
if (params.result.length) {
const r = params.result[0];
MessagePlugin.error(`${r.col.title} ${r.errorList[0].message}`);
return;
}
// 如果是 table 的父组件主动触发校验
if (params.trigger === 'parent' && !params.result.length) {
const current = editMap[currentSaveId.value];
if (!current) return;
data.value.splice(current.rowIndex, 1, current.editedRow);
MessagePlugin.success('保存成功');
updateEditState(currentSaveId.value);
}
};

const onRowEdit = (params) => {
const { row, rowIndex, col, value } = params;
const oldRowData = editMap[row.key]?.editedRow || row;
editMap[row.key] = {
...params,
editedRow: { ...oldRowData, [col.colKey]: value },
};
};

const columns = computed(() => [
{
title: 'FirstName',
colKey: 'firstName',
align: align.value,
// 编辑状态相关配置,全部集中在 edit
edit: {
// 1. 支持任意组件。需保证组件包含 `value` 和 `onChange` 两个属性,且 onChange 的第一个参数值为 new value。
// 2. 如果希望支持校验,组件还需包含 `status` 和 `tips` 属性。具体 API 含义参考 Input 组件
component: Input,
// props, 透传全部属性到 Input 组件
props: {
clearable: true,
autofocus: true,
autoWidth: true,
},
// 校验规则,此处同 Form 表单
rules: [
{ required: true, message: '不能为空' },
{ max: 10, message: '字符数量不能超过 10', type: 'warning' },
],
showEditIcon: false,
},
},
{
title: 'Framework',
colKey: 'framework',
edit: {
component: Select,
// props, 透传全部属性到 Select 组件
props: {
autoWidth: true,
options: [
{ label: 'Vue', value: 'Vue' },
{ label: 'React', value: 'React' },
{ label: 'Miniprogram', value: 'Miniprogram' },
{ label: 'Flutter', value: 'Flutter' },
],
},
showEditIcon: false,
},
},
{
title: 'Letters',
colKey: 'letters',
cell: (h, { row }) => row.letters.join('、'),
edit: {
component: Select,
// props, 透传全部属性到 Select 组件
// props 为函数时,参数有:col, row, rowIndex, colIndex, editedRow。一般用于实现编辑组件之间的联动
props: ({ col, row, rowIndex, colIndex, editedRow }) => {
console.log(col, row, rowIndex, colIndex, editedRow);
return {
multiple: true,
minCollapsedNum: 1,
autoWidth: true,
options: [
{ label: 'A', value: 'A' },
{ label: 'B', value: 'B' },
{ label: 'C', value: 'C' },
{ label: 'D', value: 'D' },
{ label: 'E', value: 'E' },
// 如果框架选择了 React,则 Letters 隐藏 G 和 H
{ label: 'G', value: 'G', show: () => editedRow.framework !== 'React' },
{ label: 'H', value: 'H', show: () => editedRow.framework !== 'React' },
].filter((t) => (t.show === undefined ? true : t.show())),
};
},
showEditIcon: false,
},
},
{
title: 'Date',
colKey: 'createTime',
className: 't-demo-col__datepicker',
// props, 透传全部属性到 DatePicker 组件
edit: {
component: DatePicker,
showEditIcon: false,
},
},
{
title: 'Operate',
colKey: 'operate',
width: 150,
cell: (h, { row }) => {
const editable = editableRowKeys.value.includes(row.key);
return (
<div class="table-operations">
{!editable && (
<Button theme="primary" variant="text" data-id={row.key} onClick={onEdit}>
编辑
</Button>
)}
{editable && (
<Button theme="primary" variant="text" data-id={row.key} onClick={onSave}>
保存
</Button>
)}
{editable && (
<Button theme="primary" variant="text" data-id={row.key} onClick={onCancel}>
取消
</Button>
)}
</div>
);
},
},
]);
</script>

<style lang="less">
.t-table-demo__editable-row {
.table-operations > button {
padding: 0 8px;
line-height: 22px;
height: 22px;
}

.t-demo-col__datepicker .t-date-picker {
width: 120px;
}
}
</style>
14 changes: 10 additions & 4 deletions examples/table/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ displayColumns | Array | - | 列配置功能中,当前显示的列。支持语
defaultDisplayColumns | Array | - | 列配置功能中,当前显示的列。非受控属性。TS 类型:`CheckboxGroupValue` | N
dragSort | String | - | 拖拽排序方式,值为 `row` 表示行拖拽排序,这种方式无法进行文本复制,慎用。值为`row-handler` 表示通过专门的 拖拽手柄 进行 行拖拽排序。值为 `col` 表示列顺序拖拽。`drag-col` 已废弃,请勿使用。可选项:row/row-handler/col/drag-col | N
dragSortOptions | Object | - | 拖拽排序扩展参数,具体参数见 [Sortable](https://github.com/SortableJS/Sortable)。TS 类型:`SortableOptions` | N
editableRowKeys | Array | - | 处于编辑状态的行。TS 类型:`Array<string | number>` | N
expandedRow | String / Slot / Function | - | 展开行内容,泛型 T 指表格数据类型。TS 类型:`TNode<TableExpandedRowParams<T>>` `interface TableExpandedRowParams<T> { row: T; index: number; columns: PrimaryTableCol<T>[] | BaseTableCol<T>[] }`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts)。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
expandedRowKeys | Array | - | 展开行。支持语法糖 `v-model:expandedRowKeys`。TS 类型:`Array<string | number>` | N
defaultExpandedRowKeys | Array | - | 展开行。非受控属性。TS 类型:`Array<string | number>` | N
expandedRowKeys | Array | [] | 展开行。支持语法糖 `v-model:expandedRowKeys`。TS 类型:`Array<string | number>` | N
defaultExpandedRowKeys | Array | [] | 展开行。非受控属性。TS 类型:`Array<string | number>` | N
expandIcon | Boolean / Slot / Function | true | 用于控制是否显示「展开图标列」,值为 `false` 则不会显示。可以精确到某一行是否显示,还可以自定义展开图标内容。`expandedRow` 存在时,该参数有效。支持全局配置 `GlobalConfigProvider`。TS 类型:`boolean | TNode<ExpandArrowRenderParams<T>>` `interface ExpandArrowRenderParams<T> { row: T; index: number }`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts)。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
expandOnRowClick | Boolean | - | 是否允许点击行展开 | N
filterIcon | Slot / Function | - | 自定义过滤图标,支持全局配置 `GlobalConfigProvider`。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
Expand All @@ -114,8 +115,8 @@ defaultFilterValue | Object | - | 过滤数据的值。非受控属性。TS 类
hideSortTips | Boolean | - | 隐藏排序文本提示,支持全局配置 `GlobalConfigProvider`,默认全局配置值为 `false` | N
indeterminateSelectedRowKeys | Array | - | 半选状态行。选中行请更为使用 `selectedRowKeys` 控制。TS 类型:`Array<string | number>` | N
multipleSort | Boolean | false | 是否支持多列排序 | N
selectedRowKeys | Array | - | 选中的行,控制属性。半选状态行请更为使用 `indeterminateSelectedRowKeys` 控制。支持语法糖 `v-model:selectedRowKeys`。TS 类型:`Array<string | number>` | N
defaultSelectedRowKeys | Array | - | 选中的行,控制属性。半选状态行请更为使用 `indeterminateSelectedRowKeys` 控制。非受控属性。TS 类型:`Array<string | number>` | N
selectedRowKeys | Array | [] | 选中行,控制属性。半选状态行请更为使用 `indeterminateSelectedRowKeys` 控制。支持语法糖 `v-model:selectedRowKeys`。TS 类型:`Array<string | number>` | N
defaultSelectedRowKeys | Array | [] | 选中行,控制属性。半选状态行请更为使用 `indeterminateSelectedRowKeys` 控制。非受控属性。TS 类型:`Array<string | number>` | N
sort | Object / Array | - | 排序控制。sortBy 排序字段;descending 是否进行降序排列。值为数组时,表示正进行多字段排序。支持语法糖 `v-model:sort`。TS 类型:`TableSort` `type TableSort = SortInfo | Array<SortInfo>` `interface SortInfo { sortBy: string; descending: boolean }`。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
defaultSort | Object / Array | - | 排序控制。sortBy 排序字段;descending 是否进行降序排列。值为数组时,表示正进行多字段排序。非受控属性。TS 类型:`TableSort` `type TableSort = SortInfo | Array<SortInfo>` `interface SortInfo { sortBy: string; descending: boolean }`。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
sortIcon | Slot / Function | - | 自定义排序图标,支持全局配置 `GlobalConfigProvider`。TS 类型:`TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
Expand All @@ -131,6 +132,8 @@ onDisplayColumnsChange | Function | | TS 类型:`(value: CheckboxGroupValue)
onDragSort | Function | | TS 类型:`(context: DragSortContext<T>) => void`<br/>拖拽排序时触发,`data` 表示排序前的数据,`newData` 表示拖拽排序结束后的新数据,`sort=row` 表示行拖拽事件触发,`sort=col` 表示列拖拽事件触发。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface DragSortContext<T> { currentIndex: number; current: T; targetIndex: number; target: T; data: T[]; newData: T[]; currentData?: T[]; e: SortableEvent; sort: 'row' | 'col' }`<br/><br/>`import { SortableEvent, SortableOptions } from 'sortablejs'`<br/> | N
onExpandChange | Function | | TS 类型:`(expandedRowKeys: Array<string | number>, options: ExpandOptions<T>) => void`<br/>展开行发生变化时触发,泛型 T 指表格数据类型。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface ExpandOptions<T> { expandedRowData: Array<T> }`<br/> | N
onFilterChange | Function | | TS 类型:`(filterValue: FilterValue, context: { col?: PrimaryTableCol<T> }) => void`<br/>过滤参数发生变化时触发,泛型 T 指表格数据类型 | N
onRowEdit | Function | | TS 类型:`(context: PrimaryTableRowEditContext<T>) => void`<br/>行编辑时触发。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`type PrimaryTableRowEditContext<T> = PrimaryTableCellParams<T> & { value: any }`<br/> | N
onRowValidate | Function | | TS 类型:`(context: PrimaryTableRowValidateContext<T>) => void`<br/>行编辑校验完成后出发。`result` 表示校验结果,`trigger=self` 表示编辑组件内部触发的校验,`trigger='parent'` 表示表格父组件触发的校验。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`type PrimaryTableRowValidateContext<T> = { result: TableRowValidateResult<T>[]; trigger: 'self' | 'parent' }`<br/><br/>`export type TableRowValidateResult<T> = PrimaryTableCellParams<T> & { errorList: AllValidateResult[]; value: any }`<br/> | N
onSelectChange | Function | | TS 类型:`(selectedRowKeys: Array<string | number>, options: SelectOptions<T>) => void`<br/>选中行发生变化时触发,泛型 T 指表格数据类型。两个参数,第一个参数为选中行 keys,第二个参数为更多参数,具体如下:`type = uncheck` 表示当前行操作为「取消行选中」;`type = check` 表示当前行操作为「行选中」; `currentRowKey` 表示当前操作行的 rowKey 值; `currentRowData` 表示当前操作行的行数据。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface SelectOptions<T> { selectedRowData: Array<T>; type: 'uncheck' | 'check'; currentRowKey?: string; currentRowData?: T }`<br/> | N
onSortChange | Function | | TS 类型:`(sort: TableSort, options: SortOptions<T>) => void`<br/>排序发生变化时触发。其中 sortBy 表示当前排序的字段,sortType 表示排序的方式,currentDataSource 表示 sorter 排序后的结果,col 表示列配置。sort 值类型为数组时表示多字段排序。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface SortOptions<T> { currentDataSource?: Array<T>; col: PrimaryTableCol }`<br/> | N

Expand All @@ -148,6 +151,8 @@ display-columns-change | `(value: CheckboxGroupValue)` | 确认列配置时触
drag-sort | `(context: DragSortContext<T>)` | 拖拽排序时触发,`data` 表示排序前的数据,`newData` 表示拖拽排序结束后的新数据,`sort=row` 表示行拖拽事件触发,`sort=col` 表示列拖拽事件触发。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface DragSortContext<T> { currentIndex: number; current: T; targetIndex: number; target: T; data: T[]; newData: T[]; currentData?: T[]; e: SortableEvent; sort: 'row' | 'col' }`<br/><br/>`import { SortableEvent, SortableOptions } from 'sortablejs'`<br/>
expand-change | `(expandedRowKeys: Array<string | number>, options: ExpandOptions<T>)` | 展开行发生变化时触发,泛型 T 指表格数据类型。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface ExpandOptions<T> { expandedRowData: Array<T> }`<br/>
filter-change | `(filterValue: FilterValue, context: { col?: PrimaryTableCol<T> })` | 过滤参数发生变化时触发,泛型 T 指表格数据类型
row-edit | `(context: PrimaryTableRowEditContext<T>)` | 行编辑时触发。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`type PrimaryTableRowEditContext<T> = PrimaryTableCellParams<T> & { value: any }`<br/>
row-validate | `(context: PrimaryTableRowValidateContext<T>)` | 行编辑校验完成后出发。`result` 表示校验结果,`trigger=self` 表示编辑组件内部触发的校验,`trigger='parent'` 表示表格父组件触发的校验。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`type PrimaryTableRowValidateContext<T> = { result: TableRowValidateResult<T>[]; trigger: 'self' | 'parent' }`<br/><br/>`export type TableRowValidateResult<T> = PrimaryTableCellParams<T> & { errorList: AllValidateResult[]; value: any }`<br/>
select-change | `(selectedRowKeys: Array<string | number>, options: SelectOptions<T>)` | 选中行发生变化时触发,泛型 T 指表格数据类型。两个参数,第一个参数为选中行 keys,第二个参数为更多参数,具体如下:`type = uncheck` 表示当前行操作为「取消行选中」;`type = check` 表示当前行操作为「行选中」; `currentRowKey` 表示当前操作行的 rowKey 值; `currentRowData` 表示当前操作行的行数据。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface SelectOptions<T> { selectedRowData: Array<T>; type: 'uncheck' | 'check'; currentRowKey?: string; currentRowData?: T }`<br/>
sort-change | `(sort: TableSort, options: SortOptions<T>)` | 排序发生变化时触发。其中 sortBy 表示当前排序的字段,sortType 表示排序的方式,currentDataSource 表示 sorter 排序后的结果,col 表示列配置。sort 值类型为数组时表示多字段排序。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts)。<br/>`interface SortOptions<T> { currentDataSource?: Array<T>; col: PrimaryTableCol }`<br/>

Expand Down Expand Up @@ -260,6 +265,7 @@ component | \- | - | 组件定义,如:`Input` `Select`。对于完全自定
onEdited | Function | - | 编辑完成后,退出编辑模式时触发。TS 类型:`(context: { trigger: string; newRowData: T; rowIndex: number }) => void` | N
props | Object | - | 透传给组件 `edit.component` 的属性。TS 类型:`{ [key: string]: any }` | N
rules | Array | - | 校验规则。TS 类型:`FormRule[]`,[Form API Documents](./form?tab=api)。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
showEditIcon | Boolean | true | 是否显示编辑图标 | N

### TableTreeConfig

Expand Down
Loading