Skip to content

Commit

Permalink
feat(table): table support RowEditorTable and CellEditorTable
Browse files Browse the repository at this point in the history
  • Loading branch information
chenshuai2144 committed May 20, 2024
1 parent af56fc8 commit 013877d
Show file tree
Hide file tree
Showing 11 changed files with 2,313 additions and 1,084 deletions.
67 changes: 67 additions & 0 deletions packages/table/src/components/EditableTable/CellEditorTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { GetRowKey } from 'antd/es/table/interface';
import React from 'react';
import { ParamsType } from '../../../../components/src';
import { ProColumns } from '../../../src/typing';
import EditableProTable, { EditableProTableProps } from './index';

export function CellEditorTable<
DataType extends Record<string, any>,
Params extends ParamsType = ParamsType,
ValueType = 'text',
>(props: EditableProTableProps<DataType, Params, ValueType>) {
const [editableKeys, setEditableRowKeys] = React.useState<React.Key[]>([]);
const [dataIndex, setDataIndex] = React.useState<any[]>([]);

const rowKey = props.rowKey || 'id';

// ============================ RowKey ============================
const getRowKey = React.useMemo<GetRowKey<any>>(() => {
if (typeof rowKey === 'function') {
return rowKey;
}
return (record: DataType, index?: number) => {
if (index === -1) {
return (record as any)?.[rowKey as string];
}
// 如果 props 中有name 的话,用index 来做行号,这样方便转化为 index
if (props.name) {
return index?.toString();
}
return (record as any)?.[rowKey as string] ?? index?.toString();
};
}, [props.name, rowKey]);
return (
<EditableProTable
bordered
pagination={false}
{...props}
editable={{
editableKeys,
...props.editable,
}}
columns={
(props?.columns?.map((item) => {
return {
...item,
editable:
dataIndex.flat(1).join('.') ===
[item.dataIndex || item.key].flat(1).join('.')
? undefined
: false,
onCell: (record: any, rowIndex: any) => {
return {
onDoubleClick: () => {
setEditableRowKeys([getRowKey(record, rowIndex)]);
setDataIndex([item.dataIndex || (item.key as string)]);
},
onBlur: () => {
setEditableRowKeys([]);
},
};
},
};
}) as ProColumns<any, ValueType>[]) || []
}
/>
);
}
60 changes: 60 additions & 0 deletions packages/table/src/components/EditableTable/RowEditorTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { GetRowKey } from 'antd/es/table/interface';
import React from 'react';
import { ParamsType } from '../../../../components/src';
import { ProColumns } from '../../../src/typing';
import EditableProTable, { EditableProTableProps } from './index';

export function RowEditorTable<
DataType extends Record<string, any>,
Params extends ParamsType = ParamsType,
ValueType = 'text',
>(props: EditableProTableProps<DataType, Params, ValueType>) {
const [editableKeys, setEditableRowKeys] = React.useState<React.Key[]>([]);

const rowKey = props.rowKey || 'id';

// ============================ RowKey ============================
const getRowKey = React.useMemo<GetRowKey<any>>(() => {
if (typeof rowKey === 'function') {
return rowKey;
}
return (record: DataType, index?: number) => {
if (index === -1) {
return (record as any)?.[rowKey as string];
}
// 如果 props 中有name 的话,用index 来做行号,这样方便转化为 index
if (props.name) {
return index?.toString();
}
return (record as any)?.[rowKey as string] ?? index?.toString();
};
}, [props.name, rowKey]);
return (
<EditableProTable
bordered
pagination={false}
{...props}
editable={{
editableKeys,
...props.editable,
}}
columns={
(props?.columns?.map((item) => {
return {
...item,
onCell: (record: any, rowIndex: any) => {
return {
onDoubleClick: () => {
setEditableRowKeys([getRowKey(record, rowIndex)]);
},
onBlur: () => {
setEditableRowKeys([]);
},
};
},
};
}) as ProColumns<any, ValueType>[]) || []
}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import type { ProColumns } from '@ant-design/pro-components';
import { CellEditorTable } from '@ant-design/pro-components';
import React, { useState } from 'react';

type DataSourceType = {
id: React.Key;
title?: string;
decs?: string;
state?: string;
created_at?: number;
children?: DataSourceType[];
};

const defaultData: DataSourceType[] = new Array(5).fill(1).map((_, index) => {
return {
id: (Date.now() + index).toString(),
title: `活动名称${index}`,
decs: '这个活动真好玩',
state: 'open',
created_at: 1590486176000,
};
});

export default () => {
const [dataSource, setDataSource] = useState<readonly DataSourceType[]>(
() => defaultData,
);

const columns: ProColumns<DataSourceType>[] = [
{
title: '活动名称',
dataIndex: 'title',
width: '30%',
formItemProps: {
rules: [
{
required: true,
whitespace: true,
message: '此项是必填项',
},
{
message: '必须包含数字',
pattern: /[0-9]/,
},
{
max: 16,
whitespace: true,
message: '最长为 16 位',
},
{
min: 6,
whitespace: true,
message: '最小为 6 位',
},
],
},
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
valueType: 'select',
valueEnum: {
all: { text: '全部', status: 'Default' },
open: {
text: '未解决',
status: 'Error',
},
closed: {
text: '已解决',
status: 'Success',
},
},
},
{
title: '描述',
dataIndex: 'decs',
},
];

return (
<>
<CellEditorTable<DataSourceType>
headerTitle="可编辑表格"
columns={columns}
rowKey="id"
scroll={{
x: 960,
}}
value={dataSource}
onChange={setDataSource}
recordCreatorProps={{
newRecordType: 'dataSource',
record: () => ({
id: Date.now(),
}),
}}
/>
</>
);
};
100 changes: 100 additions & 0 deletions packages/table/src/components/EditableTable/demos/row-editor-table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { ProColumns } from '@ant-design/pro-components';
import { RowEditorTable } from '@ant-design/pro-components';
import React, { useState } from 'react';

type DataSourceType = {
id: React.Key;
title?: string;
decs?: string;
state?: string;
created_at?: number;
children?: DataSourceType[];
};

const defaultData: DataSourceType[] = new Array(5).fill(1).map((_, index) => {
return {
id: (Date.now() + index).toString(),
title: `活动名称${index}`,
decs: '这个活动真好玩',
state: 'open',
created_at: 1590486176000,
};
});
export default () => {
const [dataSource, setDataSource] = useState<readonly DataSourceType[]>(
() => defaultData,
);

const columns: ProColumns<DataSourceType>[] = [
{
title: '活动名称',
dataIndex: 'title',
width: '30%',
formItemProps: {
rules: [
{
required: true,
whitespace: true,
message: '此项是必填项',
},
{
message: '必须包含数字',
pattern: /[0-9]/,
},
{
max: 16,
whitespace: true,
message: '最长为 16 位',
},
{
min: 6,
whitespace: true,
message: '最小为 6 位',
},
],
},
},
{
title: '状态',
key: 'state',
dataIndex: 'state',
valueType: 'select',
valueEnum: {
all: { text: '全部', status: 'Default' },
open: {
text: '未解决',
status: 'Error',
},
closed: {
text: '已解决',
status: 'Success',
},
},
},
{
title: '描述',
dataIndex: 'decs',
},
];

return (
<>
<RowEditorTable<DataSourceType>
headerTitle="可编辑表格"
columns={columns}
rowKey="id"
scroll={{
x: 960,
}}
value={dataSource}
onChange={setDataSource}
recordCreatorProps={{
newRecordType: 'dataSource',
record: () => ({
id: Date.now(),
}),
}}
/>
</>
);
};
8 changes: 8 additions & 0 deletions packages/table/src/components/EditableTable/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ atomId: EditableProTable

<code src="./demos/basic.tsx" background="var(--main-bg-color)" title="可编辑表格"></code>

### 单元格编辑

<code src="./demos/cell-editor-table.tsx" background="var(--main-bg-color)" title="单元格编辑"></code>

### 行编辑

<code src="./demos/row-editor-table.tsx" background="var(--main-bg-color)" title="行编辑"></code>

### 与 FormItem 配合

<code src="./demos/form-item.tsx" background="var(--main-bg-color)" title="与 FormItem 配合"></code>
Expand Down
21 changes: 17 additions & 4 deletions packages/table/src/components/EditableTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -500,10 +500,11 @@ function EditableTable<
</>
);
}

/**
* `FieldEditableTable` is a wrapper around `EditableTable` that adds a `Form.Item` around it
* @param props - EditableProTableProps<DataType, Params, ValueType>
* @returns A function that takes in props and returns a Form.Item component.
* 可以直接放到 Form 中的可编辑表格
* A React component that is used to create a table.
* @param props
*/
function FieldEditableTable<
DataType extends Record<string, any>,
Expand All @@ -513,7 +514,15 @@ function FieldEditableTable<
const form = ProForm.useFormInstance();

if (!props.name)
return <EditableTable<DataType, Params, ValueType> {...props} />;
return (
<EditableTable<DataType, Params, ValueType>
tableLayout="fixed"
scroll={{
x: 'max-content',
}}
{...props}
/>
);

return (
<Form.Item
Expand All @@ -534,6 +543,10 @@ function FieldEditableTable<
}}
>
<EditableTable<DataType, Params, ValueType>
tableLayout="fixed"
scroll={{
x: 'max-content',
}}
{...props}
editable={{
...props.editable,
Expand Down
Loading

0 comments on commit 013877d

Please sign in to comment.