在使用antd form做动态表单开发时,官网有如下示例:
当添加表单项后:
使用此示例可以实现动态增加、减少表单项的功能,但是当我们编辑以前添加过的form表单时,该如何赋初值,又如何支持新增和编辑使用同一组件,即可以支持没有初值和有初值两种情况。本文分享了一种解决该问题的组件封装方式。
组件使用方式:
<TagComponent
tag={tag}
label='tag'
ref={ref => (this.tagRef = ref)}
/>
tag数据格式:
[{tagLabel:'label1',tagValue:'value1'}, {tagLabel:'label2',tagValue:'value2'}]
组件代码:
import React, {Component} from 'react';
import autobind from 'class-autobind';
import {Form, Input, Row, Col, Tooltip} from 'antd';
import './index.less';
const FormItem = Form.Item;
const prefixCls = 'tag-component';
class TagComponent extends Component{
constructor(props){
super(props);
this.state = {};
autobind(this, TagComponent.prototype);
this.formItemHasLabel = {
'labelCol': {'span': 12},
'wrapperCol': {'span': 12}
};
this.formItemHasLabelPosition = {
'labelCol': {'span': 0},
'wrapperCol': {'span': 12, 'offset': 12}
};
this.formItemNoLabel = {
'labelCol': {'span': 2},
'wrapperCol': {'span': 18}
};
this.uuid = 0;
}
componentDidMount(){ // DidMount赋初值
const {tag, form} = this.props;
let formTag = [];
for(let i = 0; i < tag.length; i ++){
formTag = formTag.concat([tag[i].tagLabel, tag[i].tagValue]);
}
form.setFieldsValue({
'formTag': formTag
});
}
getInitialKeys(){
const {tag} = this.props;
let nextKeys = [];
for(let i = 0; i < tag.length; i ++){
nextKeys = nextKeys.concat([this.uuid, this.uuid + 1]);
this.uuid = this.uuid + 2;
}
return nextKeys;
}
addTag(){
const {form} = this.props;
const keys = form.getFieldValue('keys');
const nextKeys = keys.concat([this.uuid, this.uuid + 1]);
this.uuid = this.uuid + 2;
form.setFieldsValue({
'keys': nextKeys
});
}
removeTag(index){
const {form} = this.props;
// can use data-binding to get
const keys = form.getFieldValue('keys');
// We need at least one passenger
if (keys.length === 0) {
return;
}
// can use data-binding to set
keys.splice(index - 1, 2);
form.setFieldsValue({
'keys': keys
});
}
renderTagFormItems(){
const {label} = this.props;
const {getFieldDecorator, getFieldValue} = this.props.form;
const initKeys = getFieldValue('keys');
const InitialKeys = initKeys || this.getInitialKeys();
getFieldDecorator('keys', {'initialValue': InitialKeys});
const formItemHasLabel = this.formItemHasLabel;
const formItemNoLabel = this.formItemNoLabel;
const formItemHasLabelPosition = this.formItemHasLabelPosition;
const keys = getFieldValue('keys');
const formItems = keys.map((k, index) => (
<Col span={index % 2 === 0 ? 14 : 10}>
<FormItem
// eslint-disable-next-line no-nested-ternary
{...(index % 2 === 1 ? formItemNoLabel : index === 0 ? formItemHasLabel : formItemHasLabelPosition)}
// eslint-disable-next-line no-nested-ternary
label={index === 0 ? label : index % 2 === 0 ? '' : ' '}
required={false}
key={k}
>
{getFieldDecorator(`formTag[${k}]`, {
'validateTrigger': ['onChange', 'onBlur'],
'rules': index % 2 === 0 ? [{
'required': true,
'whitespace': true,
'message': '必填,支持字母、数字、"."、"_"、"-",且不超过50字符',
'pattern': /^[A-Za-z0-9_\.-]{0,50}$/g
}] : [{
'required': true,
'whitespace': true,
'message':
'必填,支持字母、数字、"."、"_"、"-",且不超过50字符',
'max': 200
}]
})(
<Input
placeholder={index % 2 === 0 ? '请输入key' : '请输入value'}
className={index % 2 === 0 ? `${prefixCls}-input-left` : `${prefixCls}-input-right`}
/>
)}
{keys.length > 0 && index % 2 === 1 ? (
<a href='javascript:;' className={`${prefixCls}-remove-btn`}>
<Tooltip placement='top' title='删除'>
<span className='dplicon_minus_circle_o' onClick={() => this.removeTag(index)} />
</Tooltip>
</a>
) : null}
</FormItem>
</Col>
)
);
return formItems;
}
render(){
const {getFieldValue} = this.props.form;
const keys = getFieldValue('keys');
const {label} = this.props;
const formItemLayout = keys && keys.length !== 0 ? this.formItemHasLabelPosition : this.formItemHasLabel;
return(
<Form>
<Row>
{this.renderTagFormItems()}
<Col span={14} style={{'textAlign': 'center'}}>
<FormItem
{... formItemLayout}
// eslint-disable-next-line no-nested-ternary
label={keys && keys.length !== 0 ? '' : label}
>
<div className={`${prefixCls}-add-box`}>
<span className={`${prefixCls}-add-btn`} onClick={this.addTag}>
<span className={`${prefixCls}-icon dplicon_plus_circle_o`} />
<span className={`${prefixCls}-add-btn-text`}>添加</span>
</span>
</div>
</FormItem>
</Col>
</Row>
</Form>
);
}
}
export default Form.create()(TagComponent);
样式文件index.less
.tag-component{
&-add{
&-box{
text-align: left;
}
&-btn{
color: #0058ff;
cursor: pointer;
width: 100%;
text-align: left;
&-text{
vertical-align: middle;
}
}
}
&-icon{
vertical-align: middle;
padding: 0 6px;
}
&-remove-btn{
cursor: pointer;
position: relative;
transition: all .3s;
margin-left: 4px;
}
&-input-left{
width: 100%;
}
&-input-right{
width: calc(~'100% - 20px');
}
}
效果如下:
初始状态、无初始值或初始值为[]:
添加表单项后:
添加值或编辑(有初始值):
对于组件的解释及用法请看下篇文件《使用antd form开发支持动态增减表单项,可选有初始值组件的一种实现方式(二)》。
地址:https://blog.csdn.net/smk108/article/details/84554386
demo地址:https://blog.csdn.net/smk108/article/details/101784236