Dynamically generate multiple form form groups in react antd, including a function to dynamically add/delete form items and a function to submit the form

In this example, we first Form.useForm()create a form instance using . Next, we use Form.Listthe component to dynamically generate multiple form items. In Form.Listthe component, we use fields.mapthe method to loop through each form item and wrap Form.Itemeach form item with the component. In Form.Itemthe component, we use labelthe attribute to specify the label, namethe attribute to specify the name of the form item, and rulesthe attribute to specify the validation rules. In the input box, we use placeholderthe attribute to specify the placeholder text. At the end of each form item, we use Buttonthe component to implement the function of deleting the form item. At the end of the form, we use Buttonthe component to implement the function of submitting the form. When the user clicks Add fieldthe button, the method will be called to adddynamically add a new form item. When the user submits the form, onFinishthe method will be called to print the contents of all form items. Finally, we index.jsrender DynamicFormthe component in the file:

Example:

The value received is

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', }, ]);

Function component:

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;

 

Guess you like

Origin blog.csdn.net/weixin_38791717/article/details/130101713