当前位置: 首页 > news >正文

【图文并茂】ant design pro 如何优雅奇妙地让创建和更新页面共用一个 form

在这里插入图片描述
在这里插入图片描述
如上图所示

在这里插入图片描述
一般来说,新建和编辑页面的内容应该是差不多的。

如果分开来写,每个 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 (<Modaltitle={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 (<ModalmaskClosable={false}width="50%"destroyOnClosetitle={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) && (<Createopen={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) && (<UpdateonSubmit={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 (<ProForminitialValues={{...values,permissions: values?.permissions?.map((permission: Permission) => permission._id),}}onFinish={async (values) => {await onFinish({...values,permissions: checkedKeys,});}}><ProForm.Group><ProFormTextrules={[{ 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}><TreecheckableonExpand={onExpand}expandedKeys={expandedKeys}autoExpandParent={autoExpandParent}onCheck={onCheck}checkedKeys={checkedKeys}onSelect={onSelect}selectedKeys={selectedKeys}treeData={permissionGroups} // Use filtered top-level groupsfieldNames={{ 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 ,所以做了一个判断即可。

或者密码这里:

        <ProFormTextrules={[{ required: newRecord, message: intl.formatMessage({ id: 'enter_password' }) }]}width="md"label={intl.formatMessage({ id: 'password' })}name="password"/>

只有新增页面才是 required: newRecord

完结。

  • 获取 ant design pro & nodejs & typescript 多角色权限动态菜单管理系统源码*
  • 我正在做的程序员赚钱副业 - Shopify 真实案例技术赚钱营销课视频教程

http://www.mrgr.cn/news/5582.html

相关文章:

  • 0x01 GlassFish 任意文件读取漏洞复现
  • 使用 Python和 FFmpeg 批量截图视频到各自文件夹中
  • 【Fiddler】Fiddler抓包工具(详细讲解)_抓包工具fiddler
  • Pulsar官方文档学习笔记——架构概览
  • 芯片后端之 PT 使用 report_timing 产生报告 之 -nets 选项
  • springboot叙州区私厨到家网站---附源码98558
  • flv和 rtmp视频负载类型的差异
  • 使用 PowerShell 自动化 Windows 系统管理任务
  • CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-
  • burpsuite xssValidator插件(xss插件)
  • 【GH】【EXCEL】P3: Set Conditional Formatting To Excel Data By Gh
  • 旅游巴士(bus)【CSPJ2023】
  • 根据正则表达式生成等价类测试用例的设计和实现思路
  • TikTok达人带货秘籍:打造从流量到转化的高效社交电商闭环
  • vue中 在scoped下通过@import引入scss的作用域?
  • 云原生周刊:Kubernetes v1.31 发布
  • 大模型入门必读书籍《大语言模型》.附pdf 免费阅读
  • SpringBoot响应式编程(4)Spring Security Reactive
  • 【区块链基础】区块链的基本概念与工作原理
  • 【MobaXterm】查找输出结果的关键字