使用antd form开发支持动态增减表单项,可选有初始值组件的一种实现方式(一)

在使用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

 

 

 

 

 

 

### 回答1: 在ant Design中,我们可以使用Form组件Form.Item组件来创建表单动态增减表单可以通过state来控制表单的数量,然后根据state中的值来渲染对应数量的表单。 首先,我们需要设置一个state来保存表单的数量,可以使用数组来保存每个表单的值,例如: ```javascript state = { formItems: [{ id: 1, value: '' }] }; ``` 然后,我们可以通过map函数来遍历表单的数组,动态生成对应数量的表单: ```javascript const { formItems } = this.state; {formItems.map(item => ( <Form.Item key={item.id}> {getFieldDecorator(`item-${item.id}`, { initialValue: item.value })(<Input />)} </Form.Item> ))} ``` 当需要增加或减少表单的数量时,我们可以通过点击按钮来触发对应的函数,例如增加表单的函数可以这样实现: ```javascript addFormItem = () => { const { formItems } = this.state; const newFormItem = { id: formItems.length + 1, value: '' }; this.setState({ formItems: [...formItems, newFormItem] }); } ``` 删除表单的函数可以这样实现: ```javascript removeFormItem = (id) => { const { formItems } = this.state; const newFormItems = formItems.filter(item => item.id !== id); this.setState({ formItems: newFormItems }); } ``` 在表单提交时,我们可以通过getFieldsValue函数获取到表单的值并进行提交操作: ```javascript handleSubmit = (e) => { e.preventDefault(); const { form, formItems } = this.props; form.validateFields((err, values) => { if (!err) { const formValues = Object.keys(values).reduce((result, key) => { const id = parseInt(key.split('-')[1]); const value = values[key]; const formItem = formItems.find(item => item.id === id); result.push({ id, value }); return result; }, []); console.log(formValues); // 进行提交操作 } }); } ``` 以上就是使用antd实现动态增减表单设置表单回显的方法,通过动态管理state中的表单数组来动态渲染、增减表单,通过getFieldsValue函数获取表单的值并进行提交操作。 ### 回答2: Antd 是一款基于 React 的 UI 组件库,它提供了一系列易于使用和美观的表单组件。在使用 Antd 动态增减表单时,我们可以很容易地实现表单设置和回显。 首先,我们可以使用 AntdForm 组件来创建表单。在表单设置方面,我们可以通过调用 Form 的 getFieldDecorator 方法来设置表单初始值、校验规则和事件处理函数等。 接着,当需要动态增减表单时,我们可以利用 Antd 的 Button 组件来触发增减操作。通过在点击事件中操作表单数据(如数组的 push、splice 等方法),我们可以动态地添加或删除表单。 对于表单的回显,我们可以在表单初始化时将表单设置为从后端获取的数据。这样,当我们动态增减表单后,原有的表单会自动填充之前的值。这个过程可以通过在 Form 组件的 initialValue 属性中设置从后端获取的数据来实现。 当用户提交表单时,我们可以通过调用 Antd 提供的 Form 的方法(如 validateFieldsAndScroll)来验证并获取表单数据。然后,我们可以将表单数据提交到后端进行处理。 总结起来,通过使用 Antd 提供的 Form 组件结合动态增减表单的操作,我们可以很方便地设置和回显表单。同时,借助 Antd 的其他组件和方法,我们还能够实现表单的校验、事件处理和提交等功能。Antd 提供了一整套完善的表单解决方案,可供我们在各种场景中灵活使用。 ### 回答3: antd是一个非常流行的React UI组件库,提供了丰富的表单组件和功能。实现动态增减表单设置表单回显有以下几个步骤: 1. 设置表单初始值:在使用antd表单组件时,可以通过`initialValues`属性设置表单初始值。假设有一个列表数据`list`,每个元素包含字段`name`和`value`,可以将其转化为初始值对象`initialValues`,其中每个字段的值对应表单初始值。 2. 动态增减表单:通过antd提供的`Form.List`组件,可以实现多个表单动态增减。在表单中需要编辑和显示列表数据时,可以使用`map()`方法循环渲染表单,并使用`remove()`方法删除不需要的表单。 3. 表单的读写绑定:在使用`Form.List`组件循环渲染表单时,可以使用`name`属性将每个表单与列表数据的对应字段关联起来,实现读写绑定。这样,当表单的值发生变化时,列表数据的对应字段值也会随之更新。 4. 表单回显:在设置表单初始值的基础上,antd表单组件会自动将初始值回显到表单中,用户可以看到之前已经填写的内容。当删除或添加表单时,表单组件会自动处理表单的重新渲染和回显。 总结:通过设置表单初始值使用`Form.List`组件实现动态增减表单表单的读写绑定以及antd的自动回显功能,可以实现antd动态增减表单设置表单回显的需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值