iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >react antd实现动态增减表单
  • 689
分享到

react antd实现动态增减表单

2024-04-02 19:04:59 689人浏览 薄情痞子
摘要

之前写动态表单遇到过坑,就是用index下标做key会导致bug,而且很严重! 今天有空写下文章记录下:怎么处理和逻辑 我用的是antd3的版本,3和4的表单有点不一样,不过差别应该

之前写动态表单遇到过坑,就是用index下标做key会导致bug,而且很严重!

今天有空写下文章记录下:怎么处理和逻辑

我用的是antd3的版本,3和4的表单有点不一样,不过差别应该不大。

需求:

1、选择类型切换展示固定的模板

2、通过新增字段可以动态增减表单里面的每一行

3、控制每一行的字段是否需要必填

4、编辑时候回填参数

效果图:

部分关键代码:


import React, { Component } from 'react';
import styles from './index.less';
import {
  Table,
  Button,
  Select,
  Popconfirm,
  Modal,
  FORM,
  Input,
  Radio,
  Row,
  Col, Tooltip,
  Icon,
  message,
  Pagination, InputNumber,
} from 'antd';

const Option = Select.Option;
const FormItem = Form.Item;

let id = 0;

@Form.create()
class Index extends Component {
  marketId = 0;
  state = {
    selectType: '',
    orderType: 1,  //文章1  地图2
    typeLoading: false,
    isEdit: false,
    lookVisible: false,
    visible: false,
    pageSize: 10,
    pageNum: 1,
    keyWord: '',
    row: {},
    typeList: {},
    mock: {},
    mapType: [{
      'fieldName': 'name',
      'isImg': 0,
      'order': 0,
      'remarks': '名称',
    }, {
      'fieldName': 'label',
      'isImg': 0,
      'order': 0,
      'remarks': '标签',
    }, {
      'fieldName': 'lon',
      'isImg': 0,
      'order': 0,
      'remarks': '经度',
    }, {
      'fieldName': 'lat',
      'isImg': 0,
      'order': 0,
      'remarks': '纬度',
    }],
    articleType: [{
      'fieldName': 'name',
      'isImg': 0,
      'order': 0,
      'remarks': '名称',
    }, {
      'fieldName': 'label',
      'isImg': 0,
      'order': 0,
      'remarks': '标签',
    }],
  };

  createValues = (values) => {
    const { row } = this.state;
    const data = [];
    const newValues = { // 用新的对象承载提交的数据
      ...values,
    };
    const fieldNameData = []; // 保存fieldName值
    const remarksData = []; // 保存remarks值
    const isImgData = []; // 保存isImg值
    const orderData = []; // 保存orderData值
    const fieldName = RegExp(/fieldName/);
    const remarks = RegExp(/remarks/);
    const isImg = RegExp(/isImg/);
    for (const key in newValues) {
      if (fieldName.test(key)) {
        fieldNameData.push(newValues[key]);
      }
    }
    for (const key in newValues) {
      if (remarks.test(key)) {
        remarksData.push(newValues[key]);
      }
    }
    for (const key in newValues) {
      if (isImg.test(key)) {
        isImgData.push(newValues[key]);
      }
    }
    for (const key in newValues) {
      if (isImg.test(key)) {
        orderData.push(newValues[key]);
      }
    }
    fieldNameData.forEach((item, index) => {
      data.push({
        fieldName: item,
        remarks: remarksData[index],
        isImg: isImgData[index],
        order: orderData[index],
        id: row.dataType ? row.dataType.id : '',
      });
    });
    return data;
  };

  handleOk = e => {
    this.props.form.validateFields((err, values) => {
      if (!err) {
        const { row, isEdit } = this.state;
        const params = {
          dataType: {
            name: values.name,
            type: values.type,
            id: row.dataType ? row.dataType.id : '',
          },
          typeFields: [],
        };
        params.typeFields = this.createValues(values);
        if (isEdit) {
          editType(params).then(res => {
            if (res.code === 0) {
              message.info('修改成功');
              this.setState({
                visible: false,
                isEdit: false,
              });
              this.fetchTypeList();
              this.props.form.resetFields();
            }
          });
        } else {
          addType(params).then(res => {
            if (res.code === 0) {
              message.info('新增成功');
              this.setState({
                visible: false,
                isEdit: false,
              });
              this.fetchTypeList();
              this.props.form.resetFields();
            }
          });
        }
      }
    });
  };

  lookOrEditTypeModal = (flag, record) => {
    const { articleType, mapType } = this.state;
    if (flag === 'add') {  //添加默认为文章模板
      this.marketId = articleType.length + 1;  //设置动态key标记长度
      this.setState({
        visible: true,
        row: { typeFields: articleType },
      });
    } else if (flag === 'edit') {
      this.setState({
        visible: true,
      });
      getType({ dataTypeId: record.id }).then(res => {
        if (res.code === 0) {
          this.marketId = res.data.typeFields.length + 1;  //设置动态key标记长度
          this.setState({
            row: res.data,
            isEdit: flag === 'edit',
          });
        }
      });
    } else {
      this.setState({
        lookVisible: true,
      });
      getType({ dataTypeId: record.id }).then(res => {
        if (res.code === 0) {
          this.setState({
            row: res.data,
          });
        }
      });
    }
  };


  onChangeType = (value) => {
    const { form } = this.props;
    const { orderType, row, articleType, mapType } = this.state;
    this.props.form.resetFields();

    const params = {};
    if (value === 1) {  //文章类型
      params['typeFields'] = articleType;
      this.marketId = articleType.length + 1;
    } else {
      params['typeFields'] = mapType;
      this.marketId = mapType.length + 1;
    }
    this.setState({
      row: params,
      orderType: value,
    });
  };
//删除方法!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  removeFile = k => {
    const { form } = this.props;
    const keys = form.getFieldValue('keys');
    if (keys.length === 1) {
      return;
    }
    form.setFieldsValue({
      keys: keys.filter(key => key !== k),
    });
  };
//添加方法!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  addFile = () => {
    const { form } = this.props;
    const keys = form.getFieldValue('keys');
    const nexTKEys = keys.concat(this.marketId++);
    form.setFieldsValue({
      keys: nextKeys,
    });
  };

  judgeIsTemplet = (data) => {
    if (!data) {
      return false;
    }
    if ((data.fieldName === 'lat') || (data.fieldName === 'lon') || (data.fieldName === 'label') || (data.fieldName === 'name')) {
      return true;
    }
  };
  handleValidator = (rule, val, callback) => {
    if (!val) {
      callback();
    }
    let validateResult = /^[5A-Za-z0-9-\_]+$/.test(val);
    if (!validateResult) {
      callback('请输入正确表字段');
    }
    callback();
  };

  columns = [
    {
      title: '类型名称',
      dataindex: 'name',
      key: 'name',
      width: 500,
    },
    {
      title: '所属类型',
      dataIndex: 'type',
      key: 'type',
      render: (text) => {
        return text === 1 ? '文章' : '地图';
      },
    },
    {
      title: '操作',
      dataIndex: 'address',
      key: 'address',
      render: (text, record) => {
        return <div>
          <Button type='link' onClick={() => this.lookOrEditTypeModal('look', record)}>查看</Button>
          <Button type='link' onClick={() => this.lookOrEditTypeModal('edit', record)}>编辑</Button>
          <Popconfirm title="确认删除?" onConfirm={() => this.deleteTypeClick(record)}>
            <Button type='link'>删除</Button>
          </Popconfirm>
        </div>;
      },
    },
  ];

  render() {
    const { selectType, typeLoading, mock, row, isEdit, typeList, keyWord, lookVisible } = this.state;
    const { getFieldDecorator, getFieldValue } = this.props.form;
    let typeFields = row.typeFields || [];
    const initData = [];
    typeFields.forEach((item, index) => {//根据真实数据,设置默认keys数组
      initData.push(index);
    });
    getFieldDecorator('keys', { initialValue: initData });  //给表单增加keys字段,并设置默认值,这里编辑时候可以生成编辑回填的效果。
    const keys = getFieldValue('keys');
    const formItems = keys.map((k) => (
      <Row gutter={12} key={k} className={styles.form_row}>
        <FormItem label="字段" key={`fieldName_${k}`}>
          {getFieldDecorator(`fieldName_${k}`, {
            initialValue: row.typeFields[k] ? row.typeFields[k].fieldName : '',
            validateTrigger: ['onChange', 'onBlur'], //校验子节点值的时机
            rules: [{
              required: true,
              message: '请输入英文字段!',
            }, {
              validator: this.handleValidator,
            }],
          })(<Input placeholder="请输入英文字段" max={30} disabled={this.judgeIsTemplet(row.typeFields[k])}/>)}
        </FormItem>
        <FormItem label="名称" key={`remarks_${k}`}>
          {getFieldDecorator(`remarks_${k}`, {
            initialValue: row.typeFields[k] ? row.typeFields[k].remarks : '',
            validateTrigger: ['onChange', 'onBlur'],
            rules: [{
              required: true,
              message: '请输入中文名称!',
            }],
          })(<Input placeholder="请输入中文名称" disabled={this.judgeIsTemplet(row.typeFields[k])}/>)}
        </FormItem>
        <FormItem label="排序" key={`order_${k}`}>
          {getFieldDecorator(`order_${k}`, {
            initialValue: row.typeFields[k] ? row.typeFields[k].order : 0,
          })(<InputNumber style={{width:75}} placeholder="排序" />)}
        </FormItem>
        <FormItem label="图片" key={k}>
          {getFieldDecorator(`isImg_${k}`, {
            initialValue: row.typeFields[k] ? row.typeFields[k].isImg : 0,
            rules: [{
              required: true,
            }],
          })(<Radio.Group disabled={this.judgeIsTemplet(row.typeFields[k])}>
            <Radio value={0}>否</Radio>
            <Radio value={1}>是</Radio>
          </Radio.Group>)}
        </FormItem>
        {!this.judgeIsTemplet(row.typeFields[k]) ? (
          <Icon type="minus-circle" onClick={() => this.removeFile(k)} title='删除'/>
        ) : null}
      </Row>
    ));


    return (
      <div className={styles.wrap_type}>
        <Modal
          title="类型管理"
          visible={this.state.visible}
          onOk={this.handleOk}
          onCancel={this.handleCancel}
          width={890}
          // className={styles.modal_type}
          maskClosable={false}
        >
          <Form layout='inline'>
            <Row style={{ textAlign: 'center', marginBottom: 14 }}>
              <FormItem label="选择类型">
                {getFieldDecorator('type', {
                  initialValue: row.dataType ? row.dataType.type : 1,
                  rules: [{
                    required: true,
                  }],
                })(<Select onChange={this.onChangeType} disabled={isEdit} style={{ width: 200 }}>
                  <Option value={1}>文章类型</Option>
                  <Option value={2}>地图类型</Option>
                  <Option value={3} disabled={true}>文件类型</Option>
                </Select>)}
              </FormItem>
              <FormItem label="类型名称">
                {getFieldDecorator('name', {
                  initialValue: row.dataType ? row.dataType.name : '',
                  rules: [{
                    required: true,
                    message: '请输入类型名称!',
                  }],
                })(<Input placeholder="请输入类型名称" style={{ width: 200 }}/>)}
              </FormItem>
            </Row>
            {formItems}
            <div style={{ margin: 'auto', textAlign: 'center' }}>
              <Button icon="plus" onClick={this.addFile} style={{ marginTop: 10 }}>新增字段</Button>
            </div>
          </Form>
        </Modal>
      </div>
    );
  }
}

export default Index;

关键地方是设置一个marketID作为动态添加的key,然后用他的值作为动态key。(千万不要用数组的下标index来作为key)!

到此这篇关于react antd实现动态增减表单的文章就介绍到这了,更多相关react antd动态增减表单内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: react antd实现动态增减表单

本文链接: https://www.lsjlt.com/news/127525.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • react antd实现动态增减表单
    之前写动态表单遇到过坑,就是用index下标做key会导致bug,而且很严重! 今天有空写下文章记录下:怎么处理和逻辑 我用的是antd3的版本,3和4的表单有点不一样,不过差别应该...
    99+
    2024-04-02
  • react+antd实现动态编辑表格数据
    本文实例为大家分享了react+antd动态编辑表格数据的具体代码,供大家参考,具体内容如下 在项目中,我们会遇到一种需求,为用户提供一份表格去编辑,而且表格中各个单元格是相关影响的...
    99+
    2024-04-02
  • react实现动态表单
    本文实例为大家分享了react实现动态表单的具体代码,供大家参考,具体内容如下 1.小要求 在工作中,我们也会碰到这样子的需求:在填写信息的时候,可以填写多个人名、多个需求、以及动态...
    99+
    2024-04-02
  • React+Antd 实现可增删改表格的示例
    目录Table/index.jsTable/model/index.jsTable/model/modules/base.jsTable/model/modules/editTabl...
    99+
    2024-04-02
  • antd+vue实现动态验证循环属性表单的思路
    希望实现查询表单的某些属性可以循环验证必填项: 需求: 1.名称,对比项,备注必填,默认为一行,可增加多行 2.根据名称,动态请求对比项列表,名称变化时,清空该行当前选择的对比项 思...
    99+
    2024-04-02
  • React如何利用Antd的Form组件实现表单功能详解
    一、构造组件 1、表单一定会包含表单域,表单域可以是输入控件,标准表单域,标签,下拉菜单,文本域等。 这里先引用了封装的表单域 <Form.Item /> 2、使用For...
    99+
    2024-04-02
  • springboot vue接口测试前端动态增删表单功能实现
    目录基于 springboot+vue 的测试平台开发页面实现1. 基础信息部分2. 请求参数部分3. 响应内容部分基于 springboot+vue 的测试平台开发 继续更新 目前...
    99+
    2024-04-02
  • react使用antd的上传组件实现文件表单一起提交功能
    本篇内容主要讲解“react使用antd的上传组件实现文件表单一起提交功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“react使用antd的上传组件实现文件表单一起提交功能”吧!项目中需要实...
    99+
    2023-06-20
  • BootStrap如何实现动态表单效果
    小编给大家分享一下BootStrap如何实现动态表单效果,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!html部分 &...
    99+
    2024-04-02
  • react实现动态选择框
    本文实例为大家分享了react实现动态选择框的具体代码,供大家参考,具体内容如下 小需求 在工作中,我们也会碰到这种需求: 为了提高用户的体验,在搜索的时候,采用灵活查询。用户可以自...
    99+
    2024-04-02
  • vue实现动态表单动态渲染组件的方式(2)
    本文实例为大家分享了vue实现动态表单动态渲染组件的方式,供大家参考,具体内容如下 思路 先把所有可能出现的表单/组件写在主页面每个表单/组件的slot 属性值要与后端返回的表单/组...
    99+
    2024-04-02
  • Python+PyQt5实现数据库表格动态增删改
    目录题目描述解题思路/算法分析/问题及解决实验代码运行结果题目描述 本次实验为连接数据库的实验,并对数据库进行一些简单的操作,要实现的基本功能如下所示,要能连接并展现数据库里的数据,...
    99+
    2024-04-02
  • vue实现动态表单动态渲染组件的方式(1)
    vue 实现动态表单/动态渲染组件的方式(一),供大家参考,具体内容如下 思路 先写好各个可能会出现的表单或者自定义的组件,引入。此时后端可能会给到一个对象型数组,每个对象有要渲染组...
    99+
    2024-04-02
  • antd table怎么实现长表格出现滚动条
    本篇内容主要讲解“antd table怎么实现长表格出现滚动条”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“antd table怎么实现长表格出现滚动条”吧!代码如下:&nb...
    99+
    2023-07-02
  • jQuery中clone()函数怎么实现表单中增加和减少输入项
    这篇文章主要介绍jQuery中clone()函数怎么实现表单中增加和减少输入项,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!之前一直没有深入了解到clone()函数的方法,所以对应表...
    99+
    2024-04-02
  • PHP实现动态表单生成工具详解
    目录Form介绍特点项目主页链接安装方法快速使用链式操作创建块表单数组配置创建块表单行内表单table表单表单包含多种input类型,包括 hiiden类型 ,text类型,radi...
    99+
    2024-04-02
  • react如何实现浮动菜单
    本篇内容介绍了“react如何实现浮动菜单”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!react实现浮动菜单的方法:1、利用onMouse...
    99+
    2023-07-04
  • 利用Struts怎么实现一个动态表单
    今天就跟大家聊聊有关利用Struts怎么实现一个动态表单,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1.手动进行定义<form-beans > <form-bea...
    99+
    2023-05-31
    struts st
  • react怎么实现浮动菜单
    本教程操作环境:Windows10系统、react18.0.0版、Dell G3电脑。react怎么实现浮动菜单?React中hover悬浮菜单的做法对于悬浮菜单,主要是借助html标签的事件机制,或者hover来实现,先看下效果图:当鼠标...
    99+
    2023-05-14
    React
  • DjangoVue实现动态菜单和动态权限
    目录用户与用户组的架构设计动态菜单和权限的设计思路与实现Vue 端如何实现动态路由Django 端如何实现动态权限随着前后端分离架构的流行,在 web 应用中,RESTful API...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作