Skip to content

Commit

Permalink
feat(table): support update any cell value with updateEditedCellValue (
Browse files Browse the repository at this point in the history
…#3522)

* feat(table): support update any cell value with updateEditedCellValue

* docs(table): update api docs

* fix(table): lint error
  • Loading branch information
chaishi authored Oct 25, 2023
1 parent 6b38e4a commit 3ae552f
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 12 deletions.
11 changes: 10 additions & 1 deletion src/table/_example/editable-row.vue
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ const columns = computed(() => [
// 校验规则,此处同 Form 表单
rules: [{ required: true, message: '不能为空' }],
showEditIcon: false,
on: ({ updateEditedCellValue }) => ({
onChange: () => {
// clear `letters` on status changed
updateEditedCellValue({ colKey: 'letters', value: [] });
},
}),
},
},
{
Expand Down Expand Up @@ -208,7 +214,10 @@ const columns = computed(() => [
};
},
// 校验规则,此处同 Form 表单
rules: [{ validator: (val) => val && val.length < 3, message: '数量不能超过 2 个' }],
rules: [
{ validator: (val) => val && val.length < 3, message: '数量不能超过 2 个' },
{ validator: (val) => Boolean(val?.length), message: '至少选择一个' },
],
showEditIcon: false,
},
},
Expand Down
13 changes: 11 additions & 2 deletions src/table/editable-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
PrimaryTableRowEditContext,
PrimaryTableRowValidateContext,
TdBaseTableProps,
TableEditableCellPropsParams,
} from './type';
import { TableClassName } from './hooks/useClassName';
import { useGlobalIcon } from '../hooks/useGlobalIcon';
Expand All @@ -27,6 +28,7 @@ export interface OnEditableChangeContext<T> extends PrimaryTableRowEditContext<T
}

export interface EditableCellProps {
rowKey: string;
row: TableRowData;
rowIndex: number;
col: PrimaryTableCol<TableRowData>;
Expand All @@ -52,6 +54,7 @@ export default defineComponent({
name: 'TableEditableCell',
props: {
row: Object as PropType<EditableCellProps['row']>,
rowKey: String,
rowIndex: Number,
col: Object as PropType<EditableCellProps['col']>,
colIndex: Number,
Expand All @@ -75,6 +78,8 @@ export default defineComponent({
onEditableChange: Function as PropType<EditableCellProps['onEditableChange']>,
},

emits: ['update-edited-cell'],

setup(props: EditableCellProps, context: SetupContext) {
const { row, col } = toRefs(props);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -87,8 +92,12 @@ export default defineComponent({

const { Edit1Icon } = useGlobalIcon({ Edit1Icon: TdEdit1Icon });

const updateEditedCellValue = (val: any) => {
editValue.value = val;
const updateEditedCellValue: TableEditableCellPropsParams<TableRowData>['updateEditedCellValue'] = (obj) => {
if (typeof obj === 'object' && obj.colKey && 'value' in obj) {
context.emit('update-edited-cell', { ...obj, rowValue: get(row.value, props.rowKey) });
} else {
editValue.value = obj;
}
};

watch([isKeepEditMode], (val) => {
Expand Down
26 changes: 26 additions & 0 deletions src/table/hooks/useEditableRow.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ref, computed } from 'vue';
import get from 'lodash/get';
import set from 'lodash/set';
import isFunction from 'lodash/isFunction';
import { PrimaryTableProps } from '../interface';
import { getEditableKeysMap } from '../../_common/js/table/utils';
Expand All @@ -10,6 +11,7 @@ import {
TableErrorListMap,
PrimaryTableInstanceFunctions,
ErrorListObjectType,
PrimaryTableCellParams,
} from '../type';
import { getCellKey } from './useRowspanAndColspan';
import { OnEditableChangeContext } from '../editable-cell';
Expand All @@ -27,6 +29,8 @@ export default function useRowEdit(props: PrimaryTableProps) {
const editableKeysMap = computed(() => getEditableKeysMap(props.editableRowKeys, props.data, props.rowKey || 'id'));
// 当前编辑的单元格
const editingCells = ref<{ [cellKey: string]: OnEditableChangeContext<TableRowData> }>({});
// 编辑状态的数据
const editedFormData = ref<{ [rowValue: string]: { [colKey: string]: {} } }>({});

const getErrorListMapByErrors = (errors: ErrorListObjectType<TableRowData>[]): TableErrorListMap => {
const errorMap: TableErrorListMap = {};
Expand Down Expand Up @@ -128,6 +132,13 @@ export default function useRowEdit(props: PrimaryTableProps) {
});
};

const onUpdateEditedCell = (params: { rowValue: any; colKey: string; value: any }) => {
if (!editedFormData.value[params.rowValue]) {
editedFormData.value[params.rowValue] = {};
}
editedFormData.value[params.rowValue][params.colKey] = params.value;
};

const onRuleChange = (context: PrimaryTableRowEditContext<TableRowData>) => {
// 编辑行,预存校验信息,方便最终校验
if (props.editableRowKeys) {
Expand Down Expand Up @@ -161,13 +172,28 @@ export default function useRowEdit(props: PrimaryTableProps) {
}
};

const getEditRowData = ({ row, col }: PrimaryTableCellParams<TableRowData>) => {
const rowValue = get(row, props.rowKey || 'id');
const editedRowValue = editedFormData.value[rowValue];
const hasEditedCellValue = editedRowValue && col.colKey in editedRowValue;
if (hasEditedCellValue) {
const tmpRow = { ...row };
set(tmpRow, col.colKey, editedRowValue[col.colKey]);
return tmpRow;
}
return row;
};

return {
editedFormData,
errorListMap,
editableKeysMap,
validateTableData,
validateRowData,
onRuleChange,
clearValidateData,
onUpdateEditedCell,
getEditRowData,
onPrimaryTableCellEditChange,
};
}
17 changes: 15 additions & 2 deletions src/table/primary-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ export default defineComponent({
validateTableData,
onRuleChange,
clearValidateData,
onUpdateEditedCell,
getEditRowData,
onPrimaryTableCellEditChange,
} = useEditableRow(props);

Expand Down Expand Up @@ -204,6 +206,15 @@ export default defineComponent({
baseTableRef: primaryTableRef,
});

const onEditableCellChange: EditableCellProps['onChange'] = (params) => {
props.onRowEdit?.(params);
onUpdateEditedCell({
rowValue: get(params.editedRow, props.rowKey || 'id'),
colKey: params.col.colKey,
value: params.value,
});
};

// 1. 影响列数量的因素有:自定义列配置、展开/收起行、多级表头;2. 影响表头内容的因素有:排序图标、筛选图标
const getColumns = (columns: PrimaryTableCol<TableRowData>[]) => {
const arr: PrimaryTableCol<TableRowData>[] = [];
Expand Down Expand Up @@ -256,10 +267,12 @@ export default defineComponent({
item.cell = (h, p: PrimaryTableCellParams<TableRowData>) => {
const cellProps: EditableCellProps = {
...p,
row: getEditRowData(p),
oldCell,
rowKey: props.rowKey || 'id',
tableBaseClass,
cellEmptyContent: props.cellEmptyContent,
onChange: props.onRowEdit,
onChange: onEditableCellChange,
onValidate: props.onRowValidate,
onRuleChange,
onEditableChange: onPrimaryTableCellEditChange,
Expand All @@ -274,7 +287,7 @@ export default defineComponent({
if (props.editableCellState) {
cellProps.readonly = !props.editableCellState(p);
}
return <EditableCell {...cellProps} v-slots={context.slots} />;
return <EditableCell {...cellProps} v-slots={context.slots} onUpdateEditedCell={onUpdateEditedCell} />;
};
}
if (item.children?.length) {
Expand Down
4 changes: 2 additions & 2 deletions src/table/table.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ abortEditOnEvent | Array | - | Typescript:`string[]` | N
component | \- | - | component definition。Typescript:`ComponentType`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
defaultEditable | Boolean | false | set default editable once | N
keepEditMode | Boolean | false | set table cell always to be editable | N
on | Function | - | Typescript:`(context: TableEditableCellPropsParams<T>) => { [eventName: string]: Function }` | N
on | Function | - | edit component events, you can update any cell value of current row with param `updateEditedCellValue`Typescript:`(context: TableEditableCellPropsParams<T>) => { [eventName: string]: Function }` | N
onEdited | Function | - | trigger on finishing editing。Typescript:`(context: PrimaryTableOnEditedContext<T>) => void` `type PrimaryTableOnEditedContext<T> = PrimaryTableCellParams<T> & { trigger: string; newRowData: T; }`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
props | Object | - | props of `edit.component`。Typescript:`TableEditableCellProps<T>` `type TableEditableCellProps<T> = TablePlainObject \| ((params: TableEditableCellPropsParams<T>) => TablePlainObject)` `interface TableEditableCellPropsParams<T> extends PrimaryTableCellParams<T> { editedRow: T; updateEditedCellValue: (val: any) => void }` `interface TablePlainObject{ [key: string]: any }`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts)[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
props | Object / Function | - | props of `edit.component`, you can update any cell value of current row with param `updateEditedCellValue`。Typescript:`TableEditableCellProps<T>` `type TableEditableCellProps<T> = TablePlainObject \| ((params: TableEditableCellPropsParams<T>) => TablePlainObject)` `interface TableEditableCellPropsParams<T> extends PrimaryTableCellParams<T> { editedRow: T; updateEditedCellValue: (val: any \| { colKey: string, value: any }) => void }` `interface TablePlainObject{ [key: string]: any }`[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts)[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
rules | Array | - | form rules。Typescript:`TableEditableCellRules<T>` `type TableEditableCellRules<T> = FormRule[] \| ((params: PrimaryTableCellParams<T>) => FormRule[])`[Form API Documents](./form?tab=api)[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
showEditIcon | Boolean | true | show edit icon | N
validateTrigger | String | 'exit' | when to trigger validate。Typescript:`'exit' \| 'change'` | N
Expand Down
4 changes: 2 additions & 2 deletions src/table/table.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ abortEditOnEvent | Array | - | 除了点击非自身元素退出编辑态之外
component | \- | - | 组件定义,如:`Input` `Select`。对于完全自定义的组件(非组件库内的组件),组件需要支持 `value``onChange` ;如果还需要支持校验规则,则组件还需实现 `tips``status` 两个 API,实现规则可参考 `Input` 组件。TS 类型:`ComponentType`[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N
defaultEditable | Boolean | false | 单元格默认状态是否为编辑态 | N
keepEditMode | Boolean | false | 设置当前列的单元格始终保持为编辑态 | N
on | Function | - | 透传给编辑组件的事件。TS 类型:`(context: TableEditableCellPropsParams<T>) => { [eventName: string]: Function }` | N
on | Function | - | 透传给编辑组件的事件,可以使用参数 `updateEditedCellValue` 更新当前行任意编辑状态单元格的值。TS 类型:`(context: TableEditableCellPropsParams<T>) => { [eventName: string]: Function }` | N
onEdited | Function | - | 编辑完成后,退出编辑模式时触发。TS 类型:`(context: PrimaryTableOnEditedContext<T>) => void` `type PrimaryTableOnEditedContext<T> = PrimaryTableCellParams<T> & { trigger: string; newRowData: T; }`[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/table/type.ts) | N
props | Object | - | 透传给组件 `edit.component` 的属性。TS 类型:`TableEditableCellProps<T>` `type TableEditableCellProps<T> = TablePlainObject \| ((params: TableEditableCellPropsParams<T>) => TablePlainObject)` `interface TableEditableCellPropsParams<T> extends PrimaryTableCellParams<T> { editedRow: T; updateEditedCellValue: (val: any) => void }` `interface TablePlainObject{ [key: string]: any }`[通用类型定义](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
props | Object / Function | - | 透传给组件 `edit.component` 的属性,可以使用 `updateEditedCellValue` 更新当前行任意编辑状态单元格的值。TS 类型:`TableEditableCellProps<T>` `type TableEditableCellProps<T> = TablePlainObject \| ((params: TableEditableCellPropsParams<T>) => TablePlainObject)` `interface TableEditableCellPropsParams<T> extends PrimaryTableCellParams<T> { editedRow: T; updateEditedCellValue: (val: any \| { colKey: string, value: any }) => void }` `interface TablePlainObject{ [key: string]: any }`[通用类型定义](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
rules | Array | - | 校验规则。TS 类型:`TableEditableCellRules<T>` `type TableEditableCellRules<T> = FormRule[] \| ((params: PrimaryTableCellParams<T>) => 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
validateTrigger | String | 'exit' | 触发校验的时机,有 2 种:退出编辑时和数据变化时。TS 类型:`'exit' \| 'change'` | N
Expand Down
6 changes: 3 additions & 3 deletions src/table/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -951,15 +951,15 @@ export interface TableEditableCellConfig<T extends TableRowData = TableRowData>
*/
keepEditMode?: boolean;
/**
* 透传给编辑组件的事件
* 透传给编辑组件的事件,可以使用参数 `updateEditedCellValue` 更新当前行任意编辑状态单元格的值
*/
on?: (context: TableEditableCellPropsParams<T>) => { [eventName: string]: Function };
/**
* 编辑完成后,退出编辑模式时触发
*/
onEdited?: (context: PrimaryTableOnEditedContext<T>) => void;
/**
* 透传给组件 `edit.component` 的属性
* 透传给组件 `edit.component` 的属性,可以使用 `updateEditedCellValue` 更新当前行任意编辑状态单元格的值
*/
props?: TableEditableCellProps<T>;
/**
Expand Down Expand Up @@ -1265,7 +1265,7 @@ export type TableEditableCellProps<T> =

export interface TableEditableCellPropsParams<T> extends PrimaryTableCellParams<T> {
editedRow: T;
updateEditedCellValue: (val: any) => void;
updateEditedCellValue: (val: any | { colKey: string; value: any }) => void;
}

export interface TablePlainObject {
Expand Down

0 comments on commit 3ae552f

Please sign in to comment.