世界上最伟大的投资就是投资自己的教育
【图文并茂】ant design pro 如何优雅奇妙地让创建和更新页面共用一个 form
随风发布于92 次阅读
如果分开来写,每个 form 都写一份代码,那就太复杂了。一改的话,可能要改两次
如何共用呢,还要做到,有时候他们有些差异的,比如用户修改的时候可以不用填密码,但是创建时一定要有密码。
创建页面
src/pages/Auth/Roles/components/Create.tsx
import { useIntl } from '@umijs/max';
import { FormInstance, Modal } from 'antd';
import BasicForm from './BasicForm';
import { values } from 'lodash';
interface Props {
open: boolean;
onOpenChange: (visible: boolean) => void;
onFinish: (formData: any) => Promise<void>;
}
interface Props {
form?: FormInstance<any>;
newRecord?: boolean;
onFinish: (formData: any) => Promise<void>;
values?: any;
}
const Create: React.FC<Props> = (props) => {
const intl = useIntl();
const { open, onOpenChange, onFinish } = props;
return (
<Modal
title={intl.formatMessage({ id: 'add_new' })}
width="45%"
open={open}
onCancel={() => onOpenChange(false)}
destroyOnClose={true}
maskClosable={false}
footer={null}
>
<BasicForm values={values} newRecord onFinish={onFinish} />
</Modal>
);
};
export default Create;
编辑页面
import { useIntl } from '@umijs/max';
import React from 'react';
import BasicForm from './BasicForm';
import { Modal } from 'antd';
export type FormValueType = Partial<API.ItemData>;
export type UpdateFormProps = {
onCancel: (visible: boolean) => void;
onSubmit: (values: FormValueType) => Promise<void>;
updateModalOpen: boolean;
values: {
roles?: { id: number }[];
} & Partial<API.ItemData>;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const { updateModalOpen, onCancel, onSubmit, values } = props;
return (
<Modal
maskClosable={false}
width="50%"
destroyOnClose
title={intl.formatMessage({ id: 'modify' })}
open={updateModalOpen}
footer={false}
onCancel={() => onCancel(false)}
>
<BasicForm values={values} onFinish={onSubmit} />
</Modal>
);
};
export default UpdateForm;
可以看到它们用的同一个 BasicForm ,只是传参可能有些不同。
index 的引用
{(access.canSuperAdmin || access.canCreateRole) && (
<Create
open={createModalOpen}
onOpenChange={handleModalOpen}
onFinish={async (value) => {
const success = await handleAdd(value as API.ItemData);
if (success) {
handleModalOpen(false);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
/>
)}
{(access.canSuperAdmin || access.canUpdateRole) && (
<Update
onSubmit={async (value) => {
const success = await handleUpdate(value);
if (success) {
handleUpdateModalOpen(false);
setCurrentRow(undefined);
if (actionRef.current) {
actionRef.current.reload();
}
}
}}
onCancel={handleUpdateModalOpen}
updateModalOpen={updateModalOpen}
values={currentRow || {}}
/>
)}
共用的 form
src/pages/Auth/Roles/components/BasicForm.tsx
import { useIntl } from '@umijs/max';
import React, { Key, useState } from 'react';
import { ProForm, ProFormText } from '@ant-design/pro-components';
import { Form, Input, Spin, Tree } from 'antd';
import useQueryList from '@/hooks/useQueryList';
import { FormInstance } from 'antd/es/form';
import { Permission } from '@/apiDataStructures/ApiDataStructure';
interface Props {
form?: FormInstance<any>;
newRecord?: boolean;
onFinish: (formData: any) => Promise<void>;
values?: any;
}
const BasicForm: React.FC<Props> = ({ newRecord, onFinish, values }) => {
const intl = useIntl();
const { items: permissionGroups, loading } = useQueryList('/permission-groups/list');
const [expandedKeys, setExpandedKeys] = useState<Key[]>([]);
const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
const [checkedKeys, setCheckedKeys] = useState<Key[] | { checked: Key[]; halfChecked: Key[] }>(
values.permissions?.map((permission: Permission) => `${permission._id}`) ?? [],
);
const [selectedKeys, setSelectedKeys] = useState<Key[]>([]);
const onExpand = (expandedKeysValue: Key[]) => {
setExpandedKeys(expandedKeysValue);
setAutoExpandParent(false);
};
const onCheck = (checkedKeysValue: Key[] | { checked: Key[]; halfChecked: Key[] }) => {
setCheckedKeys(checkedKeysValue);
console.log('checkedKeysValue', checkedKeysValue);
};
const onSelect = (selectedKeysValue: Key[]) => {
setSelectedKeys(selectedKeysValue);
};
return (
<ProForm
initialValues={{
...values,
permissions: values?.permissions?.map((permission: Permission) => permission._id),
}}
onFinish={async (values) => {
await onFinish({
...values,
permissions: checkedKeys,
});
}}
>
<ProForm.Group>
<ProFormText
rules={[{ required: true, message: intl.formatMessage({ id: 'enter_name' }) }]}
width="md"
label={intl.formatMessage({ id: 'name' })}
name="name"
/>
<ProForm.Item name="permissions" label={intl.formatMessage({ id: 'permission_choose' })}>
<Spin spinning={loading}>
<Tree
checkable
onExpand={onExpand}
expandedKeys={expandedKeys}
autoExpandParent={autoExpandParent}
onCheck={onCheck}
checkedKeys={checkedKeys}
onSelect={onSelect}
selectedKeys={selectedKeys}
treeData={permissionGroups} // Use filtered top-level groups
fieldNames={{ title: 'name', key: '_id', children: 'children' }}
/>
</Spin>
</ProForm.Item>
</ProForm.Group>
{!newRecord && (
<Form.Item name="_id" label={false}>
<Input type="hidden" />
</Form.Item>
)}
</ProForm>
);
};
export default BasicForm;
差异
如果要让创建和编辑页面有不一样的地方
我们只要传不同的值,判断一下即可
比如创建页面
<BasicForm values={values} newRecord onFinish={onFinish} />
更新页面:
<BasicForm values={values} onFinish={onSubmit} />
看到 newRecord 没有,表示是创建页面
然后 basicForm 里
{!newRecord && (
<Form.Item name="_id" label={false}>
<Input type="hidden" />
</Form.Item>
)}
我的更新页面并不需要传 _id ,所以做了一个判断即可。
或者密码这里:
<ProFormText
rules={[{ required: newRecord, message: intl.formatMessage({ id: 'enter_password' }) }]}
width="md"
label={intl.formatMessage({ id: 'password' })}
name="password"
/>
只有新增页面才是 required: newRecord
完结。
本站文章均为原创内容,如需转载请注明出处,谢谢。
0 条回复
暂无回复~~
© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn
粤公网安备 44152102000088号 | 粤ICP备19038915号
Top