FormGroup 三种模式,mode
- form,纯表单,没有提交按钮,应用场景
- 弹窗里面嵌套
- 表单分组
- submit,提交表单
- search 搜索,和 Table搭配使用
表单校验
async function onFinish(){
// 校验表单通过后,才会获取到值
const values = await form.validateFields();
// 直接获取值,不校验表单
const values = await formRef.current.getFieldsValue();
}
手动设置表单错误
form.setFieldsValue({
// '表单字段name': '值',
id: '4c6ee816'
});
form.current.setFields([
// { name: '表单字段name', value: '需要设置的值', errors: ['错误信息'] }, 当 errors 为非空数组时,表单项呈现红色,
{ name: 'id', value: '123', errors: ['error message'] }
]);
高级搜索表单参考
https://ant-design.antgroup.com/components/form-cn#components-form-demo-advanced-search
<FormGroup
fields={fields}
col={24}
style={{width: '50%'}}
okButtonProps={{
children: '提交',
}}
cancelButtonProps={{
children: '取消',
}}
confirmLoading={false}
mode='form'
/>
FormGroup
import React, { useState, forwardRef, useImperativeHandle } from 'react';
import { func, object, array, number } from 'prop-types';
import { Form, Row, Col, Space, Button } from 'antd';
import ItemField from './ItemField';
import IconExpand from './IconExpand';
export function labelCol(col = 5) {
return {
labelCol: { span: col },
wrapperCol: { span: 24 - col },
};
}
const { Item } = Form;
const fields = [
{
name: 'level',
label: '等级',
component: Checkbox.Group,
initialValue: 'a',
props: {
options: [{key: 'AA', value: 'a'}].map(key => {
return { label: <Tag level={key} />, value: key };
}),
className: 'small',
},
},
{
name: 'code',
label: '状态',
component: Select,
props: {
options: [],
mode: 'multiple',
placeholder: `${PLACEHOLDER.select}`,
valueKey: 'label'
},
},
{ name: 'title', label: '事件名称' },
{
name: 'time',
label: '创建时间',
component: DatePicker,
props: {
className: 'full',
placeholder: `${PLACEHOLDER.select}时间`,
},
},
{
name: 'user',
label: '用户',
component: Select,
// 组件的 props
props: {
url: '/api/v1/users',
mode: 'tags',
},
},
];
const FormRef = forwardRef(FormGroup);
FormRef.propTypes = {
fields: array.isRequired,
onChange: func,
total: number,
span: number,
};
FormRef.defaultProps = {
onChange: () => {},
total: 3,
span: 8,
};
export default FormRef;
function FormGroup(props, ref) {
const {fields, onChange, total, span } = props;
const [form] = Form.useForm();
const [expand, setExpand] = useState(false);
// const nameValue = Form.useWatch('name', form);
useImperativeHandle(ref, () => form);
return (
<Form
{...labelCol(6)}
form={form}
onValuesChange={onChange}
>
<Row gutter={24}>
<ItemField
fields={fields}
expand={expand}
total={total}
/>
<Col span={span}>
<Item wrapperCol={{ offset: 4 }}>
<Space>
<Button type="primary" htmlType="submit">
查询
</Button>
<Button onClick={() => form.resetFields() }>
重置
</Button>
<IconExpand
expand={expand}
setExpand={setExpand}
/>
</Space>
</Item>
</Col>
</Row>
</Form>
);
}
ItemField
import React, { useMemo } from 'react';
import { array, bool, number } from 'prop-types';
import { Col, Form } from 'antd';
import ItemComponent from './ItemComponent';
const { Item } = Form;
ItemField.propTypes = {
fields: array.isRequired,
total: number.isRequired,
expand: bool.isRequired,
col: number.isRequired,
};
function ItemField({ fields, total, expand, col, isSearch }) {
// 初始化显示多少个表单
const source = useMemo(() => {
if (!isSearch) return fields;
const { length } = fields;
return fields.slice(0, expand ? length : total)
}, [fields, expand, total, isSearch ]);
const children = [];
for (const [index, item] of source.entries()) {
const { span = 8, label, name, rules, component, props } = item;
const itemElement = (
<Col span={col || span} key={index}>
<Item
label={label}
name={name}
rules={rules}
>
<ItemComponent
component={component}
props={props}
label={label}
/>
</Item>
</Col>
);
children.push(itemElement);
}
return children;
}
export default ItemField
ItemComponent
import React, {
createElement,
// 是不是有效的 ReactElement
isValidElement,
} from 'react';
import {
Button,
Input,
InputNumber,
DatePicker,
Checkbox,
Radio,
Switch,
Select,
AutoComplete,
} from 'antd';
import { isObject, isFunction } from 'lodash';
const { TextArea, Password } = Input;
const { RangePicker } = DatePicker;
export const PLACEHOLDER = {
input: '请输入',
select: '请选择',
};
// 表单组件
const COMPONENTS = {
AutoComplete,
Button,
Checkbox,
CheckboxGroup: Checkbox.Group,
DatePicker,
Input,
InputNumber,
Password,
TextArea,
RadioGroup: Radio.Group,
Switch,
Select,
RangePicker,
};
// 不要忽略 rest的 value, onChange参数
function ItemComponent({ component, props, label, ...rest }) {
// 默认组件 component = Input
let Component = Input;
// 如果是 React组件
if (isValidElement(component) || isFunction(component)) {
Component = component
}
// component 是字符串
else if (COMPONENTS[component]) {
Component = COMPONENTS[component];
}
// 动态创建表单
const defaultProps = isObject(props)
? props
: { placeholder: `${PLACEHOLDER.input}${label}` };
return createElement(Component, {
...defaultProps,
...rest,
});
}
export default ItemComponent
IconExpand
切换上下箭头
import React, { useState } from 'react';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
export function IconExpand({ expand, setExpand }) {
return (
<a
onClick={() => setExpand(!expand)}
rel="noopener noreferrer nofollow"
>
{expand ? <UpOutlined /> : <DownOutlined />}
{expand ? ' 收起' : ' 展开'}
</a>
);
}