在react antd中动态生成多个 form表单组,包括一个动态添加/删除表单项的功能和一个提交表单的功能

在这个示例中,我们首先使用 Form.useForm() 创建一个表单实例。接着,我们使用 Form.List 组件来动态生成多个表单项。在 Form.List 组件中,我们使用 fields.map 方法循环渲染每个表单项,并使用 Form.Item 组件包裹每个表单项。在 Form.Item 组件中,我们使用 label 属性指定标签,使用 name 属性指定表单项的名称,使用 rules 属性指定验证规则。在输入框中,我们使用 placeholder 属性来指定占位文本。 在每个表单项的最后,我们使用 Button 组件来实现删除表单项的功能。在表单的最后,我们使用 Button 组件来实现提交表单的功能。当用户点击 Add field 按钮时,将会调用 add 方法,动态添加一个新的表单项。当用户提交表单时,将会调用 onFinish 方法,打印所有表单项的内容。 最后,我们在 index.js 文件中渲染 DynamicForm 组件:

示例:

接收传入的值为

const [formData, setFormData] = useState([ { cpu: 1, gpu: 3, memory: 1, frequency: 'week', day: 1, startTimeFormat: '00:00:00', endTimeFormat: '02:00:00', }, { cpu: 2, gpu: 4, memory: 1, frequency: 'day', day: 1, startTimeFormat: '00:00:00', endTimeFormat: '02:00:00', }, ]);

函数组件:

import React, { useState , useEffect,forwardRef, useImperativeHandle} from 'react';
import {
  Form, Input,
  Button,
  Table,
  message,
  InputNumber,
  Spin, Radio,
  Modal,
  Card,
  Row,
  Col, TimePicker,
  Select,
} from 'antd';
import moment from "moment";

import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons';
const { Option } = Select;
import styles from "./index.module.less";

const TimescrollTemplate = [
  { value: 'month', name: '月' },
  { value: 'week', name: '周' },
  { value: 'day', name: '天' },
]

function FormItem({ formItem, delShow, index, onChange, onDelete }) {
  const formatTime = (time) => {
    if (!time) {
      return '00:00:00';
    }
    const hours = time.hours().toString().padStart(2, '0');
    const minutes = time.minutes().toString().padStart(2, '0');
    const seconds = time.seconds().toString().padStart(2, '0');
    return `${hours}:${minutes}:${seconds}`;
  };
  const handleInputChange = (index, name, value) => {
    console.log(index, name, value, "index, name, value")
    if (name, value) {
      if (name == "startTimeFormat") {
        // const formattedTime = formatTime(value);
        const [startTime, endTime] = value
        console.log(startTime, endTime, "startTime, endTime")
        onChange(index, "startTimeFormat", formatTime(startTime));
        onChange(index, "endTimeFormat", formatTime(endTime));
      } else {
        onChange(index, name, value);
      }
    }
  };
  return (
    <>
      <Row gutter={[0, 24]} className={styles.listBody}>
        <Col className="gutter-row" span={10}>
          <Row gutter={[0, 24]}  >

            <Col className="gutter-row" style={
   
   {
              textAlign: "left",
              lineHeight: '32px',

            }} span={8}>
              <div className={styles.rowTie}>CPU(核)</div>

              <InputNumber min={0} style={
   
   { maxwidth: 160, marginLeft: 24, borderRadius: 2 }} value={formItem.cpu}
                name="cpu"
                onChange={(newValue) => handleInputChange(index, 'cpu', newValue)}
              />

            </Col>
            <Col className="gutter-row" style={
   
   {
              lineHeight: '32px',
              textAlign: "left"
            }} span={8}>
              <div className={styles.rowTie}>GPU(个)</div>
              <InputNumber
                name="gpu"
                value={formItem.gpu}
                onChange={(newValue) => handleInputChange(index, 'gpu', newValue)}
                min={0} style={
   
   { maxwidth: 160, marginLeft: 24, borderRadius: 2 }} />

            </Col>
            <Col className="gutter-row" style={
   
   {
              lineHeight: '32px',
              textAlign: "left"
            }} span={8}>
              <div className={styles.rowTie}>内存(G)</div>

              <InputNumber
                name="memory"
                value={formItem.memory}
                onChange={(newValue) => handleInputChange(index, 'memory', newValue)}
                min={0} style={
   
   { maxwidth: 160, marginLeft: 24, borderRadius: 2 }} />

            </Col>
          </Row>
        </Col>
        <Col className="gutter-row" span={14}>
          <div style={
   
   {
            textAlign: "left",
            fontWeight: 500,
            marginLeft: 24,
            lineHeight: "32px"
          }}>时间段</div>
          <div style={
   
   {
            marginLeft: 24, display: "flex", lineHeight: "32px", color: "#999"
          }}>
            在每

            <Select
              placeholder="天"
              name="frequency"
              value={formItem.frequency}
              onChange={(newValue) => handleInputChange(index, 'frequency', newValue)}

              style={
   
   { borderRadius: 2, marginLeft: 5 }}
            >
              {(
                TimescrollTemplate || []).map((item) => (
                  <Select.Option key={item.value} value={item.value}>
                    {item.name}
                  </Select.Option>
                ))}
            </Select>


            <Select
              type="number"
              name="day"
              value={formItem.day}
              onChange={(newValue) => handleInputChange(index, 'day', newValue)}
              mode="tags"
              placeholder="请选择执行日"
              style={
   
   { overflowY: 'auto', width: 200,maxHeight:32, marginLeft: 10 }}
            >
              {Array.from({ length: 31 }, (_, index) => index + 1).map((item,index) => (
                <Select.Option key={item.index} value={item}>
                  {item}
                </Select.Option>
              ))}

            </Select>
            <TimePicker.RangePicker
              name="startTimeFormat"
              onChange={(newValue) => handleInputChange(index, 'startTimeFormat', newValue)}
              size="small"
              value={
                // moment(formItem.startTimeFormat, 'HH:mm:ss')
                [moment(formItem.startTimeFormat, 'HH:mm:ss'), moment(formItem.endTimeFormat, 'HH:mm:ss')]
              }
              style={
   
   { marginLeft: 10, width: 200 }} />

            {/* <TimePicker
              name="endTimeFormat"
              size="small"
              value={moment(formItem.endTimeFormat, 'HH:mm:ss')}
              onChange={(newValue) => handleInputChange(index, 'endTimeFormat', newValue)}
              style={
   
   { marginLeft: 10, width: 200 }} /> */}
            {delShow &&
              <div
                style={
   
   {
                  marginLeft: 5, position: 'absolute',
                  right: '24px',
                  top: '27px'
                }}
              >
                <a onClick={() => onDelete(index)} >删除</a>
              </div>
            }
          </div>
        </Col>

      </Row>

    </>

  );
}
const DynamicForm =  forwardRef(({ onSubmit, value = [] }, ref) => {
  console.log(value,"value")

  const [formData, setFormData] = useState(value);
  console.log(formData,"formData")
  useEffect(() => {
    setFormData(value);
  }, [value]);
  const handleFormSubmit = (event) => {
    event.preventDefault();
    console.log(formData); // 打印表单数据
    onSubmit(formData);
  };
  useImperativeHandle(ref, () => ({ handleFormSubmit }));
  const handleFormItemChange = (index, name, value) => {
    console.log(index, name, value, "index, name, value")
    setFormData((prevFormData) => {
      const newFormData = [...prevFormData];
      newFormData[index][name] = value;
      return newFormData;
    });
  };
  const handleFormItemDelete = (index) => {
    setFormData((prevFormData) => {
      const newFormData = [...prevFormData];
      newFormData.splice(index, 1);
      return newFormData;
    });
  };
  const handleFormAdd = () => {
    setFormData((prevFormData) => [
      ...prevFormData,
      {
        cpu: 1,
        gpu: 1,
        memory: 1,
        frequency: 'month',
        day: 1,
        startTimeFormat: '00:00:00',
        endTimeFormat: '00:00:00',
      },
    ]);
  };
  return (
    <form onSubmit={handleFormSubmit}>
      {formData.map((formItem, index) => (
        <FormItem
          key={index}
          formItem={formItem}
          index={index}
          delShow={formData.length > 1}
          onChange={handleFormItemChange}
          onDelete={handleFormItemDelete}
        />
      ))}

      <div >
        <Button style={
   
   { textAlign: 'center', width: 400 }}   type="primary" onClick={handleFormAdd} icon={<PlusOutlined />}>
        添加资源评估
        </Button>
      </div>
      {/* <button type="submit">提交</button> */}
    </form>
  );
});
export default DynamicForm;

猜你喜欢

转载自blog.csdn.net/weixin_38791717/article/details/130101713