In this example, we first
Form.useForm()
create a form instance using . Next, we useForm.List
the component to dynamically generate multiple form items. InForm.List
the component, we usefields.map
the method to loop through each form item and wrapForm.Item
each form item with the component. InForm.Item
the component, we uselabel
the attribute to specify the label,name
the attribute to specify the name of the form item, andrules
the attribute to specify the validation rules. In the input box, we useplaceholder
the attribute to specify the placeholder text. At the end of each form item, we useButton
the component to implement the function of deleting the form item. At the end of the form, we useButton
the component to implement the function of submitting the form. When the user clicksAdd field
the button, the method will be called toadd
dynamically add a new form item. When the user submits the form,onFinish
the method will be called to print the contents of all form items. Finally, weindex.js
renderDynamicForm
the 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;