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

1. add useEditableRow 2. 可选中行,选择组件的扩大点击范围 3.拖拽调整宽度,非边框模式,悬浮到表头时,显示表头边框 #1232

Merged
merged 10 commits into from
Jul 18, 2022
1 change: 1 addition & 0 deletions examples/table/demos/base.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
:table-layout="tableLayout ? 'auto' : 'fixed'"
:size="size"
:pagination="pagination"
resizable
@row-click="handleRowClick"
/>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/table/base-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export default defineComponent({
[tableBaseClass.multipleHeader]: isMultipleHeader.value,
[tableColFixedClasses.leftShadow]: showColumnShadow.left,
[tableColFixedClasses.rightShadow]: showColumnShadow.right,
[tableBaseClass.columnResizableTable]: props.resizable,
},
]);

Expand Down
4 changes: 2 additions & 2 deletions src/table/editable-cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default defineComponent({
default: undefined,
},
errors: {
type: Object as PropType<EditableCellProps['errors']>,
type: Array as PropType<EditableCellProps['errors']>,
default: undefined,
},
onChange: Function as PropType<EditableCellProps['onChange']>,
Expand Down Expand Up @@ -115,7 +115,7 @@ export default defineComponent({
],
trigger,
};
if (!col.value.edit?.rules) {
if (!col.value.edit || !col.value.edit.rules) {
props.onValidate?.(params);
resolve(true);
return;
Expand Down
2 changes: 2 additions & 0 deletions src/table/hooks/useClassName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default function useClassName() {
const classNames = {
tableBaseClass: {
table: `${classPrefix.value}-table`,
columnResizableTable: `${classPrefix.value}-table--column-resizable`,
overflowVisible: `${classPrefix.value}-table--overflow-visible`,
body: `${classPrefix.value}-table__body`,
content: `${classPrefix.value}-table__content`,
Expand Down Expand Up @@ -128,6 +129,7 @@ export default function useClassName() {
tableSelectedClasses: {
selected: `${classPrefix.value}-table__row--selected`,
disabled: `${classPrefix.value}-table__row--disabled`,
checkCell: `${classPrefix.value}-table__cell-check`,
},

// 过滤功能,全部类名
Expand Down
76 changes: 76 additions & 0 deletions src/table/hooks/useEditableRow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { ref, computed } from 'vue';
import get from 'lodash/get';
import { PrimaryTableProps } from '../interface';
import { getEditableKeysMap } from '../utils';
import { AllValidateResult } from '../../form/type';
import { PrimaryTableRowEditContext, PrimaryTableRowValidateContext, TableRowData } from '../type';
import { validate } from '../../form/form-model';

const cellRuleMap = new Map<any, PrimaryTableRowEditContext<TableRowData>[]>();

export type ErrorListType = { [key: string]: AllValidateResult[] };

export default function useRowEdit(props: PrimaryTableProps) {
const errorListMap = ref<ErrorListType>({});
const editableKeysMap = computed(() => getEditableKeysMap(props.editableRowKeys, props.data, props.rowKey || 'id'));

const validateRowData = (rowValue: any) => {
const rowRules = cellRuleMap.get(rowValue);
const list = rowRules.map(
(item) =>
new Promise<PrimaryTableRowEditContext<TableRowData> & { errorList: AllValidateResult[] }>((resolve) => {
const { value, col } = item;
if (!col.edit || !col.edit.rules || !col.edit.rules.length) {
resolve({ ...item, errorList: [] });
return;
}
validate(value, col.edit.rules).then((r) => {
resolve({ ...item, errorList: r.filter((t) => !t.result) });
});
}),
);
Promise.all(list).then((results) => {
const errorMap: ErrorListType = {};
const errors = results.filter((t) => t.errorList.length);
errors.forEach(({ row, col, errorList }) => {
const rowValue = get(row, props.rowKey || 'id');
const key = [rowValue, col.colKey].join();
errorMap[key] = errorList;
});
errorListMap.value = errorMap;
// 缺少校验文本显示
props.onRowValidate?.({ trigger: 'parent', result: errors });
});
};

const onRuleChange = (context: PrimaryTableRowEditContext<TableRowData>) => {
// 编辑行,预存校验信息,方便最终校验
if (props.editableRowKeys) {
const rowValue = get(context.row, props.rowKey || 'id');
const rules = cellRuleMap.get(rowValue);
if (rules) {
const index = rules.findIndex((t) => t.col.colKey === context.col.colKey);
if (index === -1) {
rules.concat(context);
} else {
rules[index].value = context.value;
}
cellRuleMap.set(rowValue, rules);
} else {
cellRuleMap.set(rowValue, [context]);
}
}
};

const clearValidateData = () => {
errorListMap.value = {};
};

return {
errorListMap,
editableKeysMap,
validateRowData,
onRuleChange,
clearValidateData,
};
}
9 changes: 6 additions & 3 deletions src/table/hooks/useRowSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ import {
TdPrimaryTableProps,
} from '../type';
import { filterDataByIds, isRowSelectedDisabled } from '../utils';
import useClassName from './useClassName';
import { TableClassName } from './useClassName';
import Checkbox from '../../checkbox';
import Radio from '../../radio';
import log from '../../_common/js/log';

export default function useRowSelect(props: TdPrimaryTableProps) {
export default function useRowSelect(
props: TdPrimaryTableProps,
tableSelectedClasses: TableClassName['tableSelectedClasses'],
) {
const { selectedRowKeys, columns, data, rowKey } = toRefs(props);
const { tableSelectedClasses } = useClassName();
const selectedRowClassNames = ref();
const [tSelectedRowKeys, setTSelectedRowKeys] = useDefaultValue(
selectedRowKeys,
Expand Down Expand Up @@ -147,6 +149,7 @@ export default function useRowSelect(props: TdPrimaryTableProps) {
return {
...col,
width: col.width || 64,
className: tableSelectedClasses.checkCell,
cell: (_: typeof h, p: PrimaryTableCellParams<TableRowData>) => renderSelectCell(p),
title: col.type === 'multiple' ? getSelectedHeader() : '',
};
Expand Down
66 changes: 6 additions & 60 deletions src/table/primary-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ import useAsyncLoading from './hooks/useAsyncLoading';
import EditableCell, { EditableCellProps } from './editable-cell';
import { PageInfo } from '../pagination';
import useClassName from './hooks/useClassName';
import { getEditableKeysMap } from './utils';
import { validate } from '../form/form-model';
import { AllValidateResult } from '../form/type';
import useEditableRow from './hooks/useEditableRow';

export { BASE_TABLE_ALL_EVENTS } from './base-table';

Expand Down Expand Up @@ -66,9 +64,8 @@ export default defineComponent({
setup(props: TdPrimaryTableProps, context: SetupContext) {
const renderTNode = useTNodeJSX();
const { columns, columnController } = toRefs(props);
const errorListMap = ref<Map<string, AllValidateResult[]>>(new Map());
const primaryTableRef = ref(null);
const { tableDraggableClasses, tableBaseClass } = useClassName();
const { tableDraggableClasses, tableBaseClass, tableSelectedClasses } = useClassName();
// 自定义列配置功能
const { tDisplayColumns, renderColumnController } = useColumnController(props, context);
// 展开/收起行功能
Expand All @@ -77,7 +74,7 @@ export default defineComponent({
// 排序功能
const { renderSortIcon } = useSorter(props, context);
// 行选中功能
const { formatToRowSelectColumn, selectedRowClassNames } = useRowSelect(props);
const { formatToRowSelectColumn, selectedRowClassNames } = useRowSelect(props, tableSelectedClasses);
// 过滤功能
const {
hasEmptyCondition,
Expand All @@ -94,6 +91,8 @@ export default defineComponent({
const { renderTitleWidthIcon } = useTableHeader(props);
const { renderAsyncLoading } = useAsyncLoading(props, context);

const { errorListMap, editableKeysMap, validateRowData, onRuleChange, clearValidateData } = useEditableRow(props);

const primaryTableClasses = computed(() => {
return {
[tableDraggableClasses.colDraggable]: isColDraggable.value,
Expand All @@ -119,65 +118,12 @@ export default defineComponent({
return tAttributes.filter((v) => v);
});

const editableKeysMap = computed(() => getEditableKeysMap(props.editableRowKeys, props.data, props.rowKey || 'id'));

// 多个 Hook 共用 primaryTableRef
onMounted(() => {
setFilterPrimaryTableRef(primaryTableRef.value);
setDragSortPrimaryTableRef(primaryTableRef.value);
});

const validateRowData = (rowValue: any) => {
const rowRules = cellRuleMap.get(rowValue);
const list = rowRules.map(
(item) =>
new Promise<PrimaryTableRowEditContext<TableRowData> & { errorList: AllValidateResult[] }>((resolve) => {
const { value, col } = item;
if (!col.edit || !col.edit.rules || !col.edit.rules.length) {
resolve({ ...item, errorList: [] });
return;
}
validate(value, col.edit.rules).then((r) => {
resolve({ ...item, errorList: r.filter((t) => !t.result) });
});
}),
);
Promise.all(list).then((results) => {
const errors = results.filter((t) => t.errorList.length);
errorListMap.value.clear();
errors.forEach(({ row, col, errorList }) => {
const rowValue = get(row, props.rowKey || 'id');
const key = [rowValue, col.colKey].join();
errorListMap.value.set(key, errorList);
});
// 缺少校验文本显示
props.onRowValidate?.({ trigger: 'parent', result: errors });
});
};

const clearValidateData = () => {
errorListMap.value.clear();
};

const onRuleChange = (context: PrimaryTableRowEditContext<TableRowData>) => {
// 编辑行,预存校验信息,方便最终校验
if (props.editableRowKeys) {
const rowValue = get(context.row, props.rowKey || 'id');
const rules = cellRuleMap.get(rowValue);
if (rules) {
const index = rules.findIndex((t) => t.col.colKey === context.col.colKey);
if (index === -1) {
rules.concat(context);
} else {
rules[index].value = context.value;
}
cellRuleMap.set(rowValue, rules);
} else {
cellRuleMap.set(rowValue, [context]);
}
}
};

// 对外暴露的方法
context.expose({
validateRowData,
Expand Down Expand Up @@ -225,7 +171,7 @@ export default defineComponent({
const rowValue = get(p.row, props.rowKey || 'id');
cellProps.editable = editableKeysMap.value[rowValue] || false;
const key = [rowValue, p.col.colKey].join();
const errorList = errorListMap.value?.get(key);
const errorList = errorListMap.value?.[key];
errorList && (cellProps.errors = errorList);
}
return <EditableCell {...cellProps} v-slots={context.slots} />;
Expand Down
Loading