V3的时候做过相关的表单,参照官方文档,但是当时是通过数值及数组控制相关的展示,在getDerivedStateFromProps中判断返显及修改值时非常麻烦,新版本的V4就简单很多了,示例图如下:
微信截图_20200315210946.png
一、引入对应的动态表单组件
import React from 'react';
import { Form, Button } from 'antd';
import DymicForm from './Dymic';
const formItemLayoutWithOutLabel = {
wrapperCol: {
xs: { span: 24, offset: 0 },
sm: { span: 20, offset: 4 },
},
};
const DynamicFieldSet = () => {
const onFinish = values => {
console.log('Received values of form:', values);
};
return (
<Form
name='dynamic_form_item'
{ ...formItemLayoutWithOutLabel }
initialValues={ {
names: [
{
key: '147.118.114',
value: 'www.xxx.com',
},
{
key: '133,144,233',
value: 'www.fff.com',
},
],
} }
onFinish={ onFinish }>
<DymicForm
label='网关'
name='names'
placeholders={ ['请输入相关IP!', '请输入对应域名!'] } />
<Form.Item>
<Button htmlType='submit' type='primary'>
提交
</Button>
</Form.Item>
</Form>
);
};
export default DynamicFieldSet;
二、DymicForm组件
import React from 'react';
import { Form } from 'antd';
import PropTypes from 'prop-types';
import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons';
import PriceInput from './inpux';
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 },
},
};
const formItemLayoutWithOutLabel = {
wrapperCol: {
xs: { span: 24, offset: 0 },
sm: { span: 20, offset: 4 },
},
};
const DynamicFieldSet = ({ name, label, placeholders }) => {
return (
<Form.List name={ name }>
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item
{ ...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel) }
key={ field.key }
label={ index === 0 ? label : '' }
required={ false }>
<Form.Item
{ ...field }
noStyle
rules={ [
{
validator: async(rule, value) => {
if (value.key === undefined || value.value === undefined || value.key === '' || value.value === '') {
throw new Error('请填写完整!');
}
},
},
] }
validateTrigger={ ['onChange', 'onBlur'] }>
<PriceInput onChange={ () => {} } placeholders={ placeholders } style={ { width: '60%', marginRight: 8 } } />
</Form.Item>
{index === fields.length - 1 ? (
<PlusCircleOutlined
onClick={ () => {add();} }
style={ { marginLeft: 5, position: 'relative', top: 5, color: '#3879d9', cursor: 'point', fontSize: 20 } } />
) : null}
{fields.length > 1 ? (
<MinusCircleOutlined
onClick={ () => {
remove(field.name);
} }
style={ { marginLeft: 5, color: 'red', position: 'relative', top: 5, cursor: 'point', fontSize: 20 } } />
) : null}
</Form.Item>
))}
</div>
);
}}
</Form.List>
);
};
DynamicFieldSet.propTypes = {
label: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
placeholders: PropTypes.array.isRequired,
};
export default DynamicFieldSet;
三、PriceInput组件
/* eslint-disable react/prop-types */
import React from 'react';
import { Input } from 'antd';
const InputGroup = Input.Group;
const PriceInput = ({ size, value = {}, placeholders, onChange, index }) => {
const handleFirstChange = e => {
triggerChange({ key: e.target.value });
};
const handleSecondChange = e => {
triggerChange({ value: e.target.value });
};
const triggerChange = changedValue => {
if (onChange) {
onChange({
...value,
...changedValue,
}, index);
}
};
return (
<div style={ { width: '85%', display: 'inline-block' } }>
<InputGroup compact>
<Input
onChange={ handleFirstChange }
placeholder={ placeholders[0] || '' }
size={ size }
style={ { width: '50%' } }
type='text'
value={ value.key } />
<Input
onChange={ handleSecondChange }
placeholder={ placeholders[1] || '' }
size={ size }
style={ { width: '50%' } }
type='text'
value={ value.value } />
</InputGroup>
</div>
);
};
export default PriceInput;
OVER~ 校验规则及个性化封装请根据自己实际项目操作!
如果你有更好的办法,烦请留言我了
网友评论