基于Ant Design的动态表单:隐藏数据库空值表单项与模态框表单重置实现问询
解决方案:处理空值表单项与表单重置问题
我来帮你搞定这两个问题,咱们分两步走:
1. 过滤数据库返回的空值表单项
数据库里的全空条目会被Form.List直接渲染出来,所以第一步要先把这些无意义的空条目过滤掉。我们需要在组件内部对传入的questionData做预处理,只保留有实际内容的题目部分;要是过滤后没有有效条目,就留一个空的默认项用来添加新内容。
2. 模态框打开时强制重置表单
现在你只在关闭模态框时重置表单,但打开的时候也需要重新初始化,确保每次打开都是干净的状态,不会残留之前的空条目或旧数据。
修改后的完整组件代码
import { useEffect } from 'react'; import { Modal, Form, Input, Space, Row, Col, Button, MinusCircleOutlined, PlusOutlined } from 'antd'; import { useDispatch } from 'react-redux'; const AddPartQuestionModalAgain = ({ isModalVisible, hideModal, questionData = { question_no: '', question_parts: [{ part_desc: '', part_total_marks: '', part_guided_answer: [{ part_model_ans: '', part_answer_mark: '' }] }], }, }) => { const dispatch = useDispatch(); let formInput; // 监听模态框显示状态,打开时重置并初始化表单 useEffect(() => { if (isModalVisible && formInput) { // 过滤全空的question_parts条目 const cleanedQuestionParts = questionData.question_parts.filter(part => { // 检查当前题目部分的核心字段是否全为空 const isPartEmpty = (part.part_desc == null || part.part_desc.trim() === '') && (part.part_total_marks == null || part.part_total_marks.trim() === ''); // 检查该部分的引导答案是否全为空 const isGuidedAnswersEmpty = !part.part_guided_answer || part.part_guided_answer.every(ans => (ans.part_model_ans == null || ans.part_model_ans.trim() === '') && (ans.part_answer_mark == null || ans.part_answer_mark.trim() === '') ); // 只要有一个字段有内容,就保留该条目 return !(isPartEmpty && isGuidedAnswersEmpty); }); // 如果过滤后没有条目,设置一个空的默认题目部分 const finalQuestionParts = cleanedQuestionParts.length > 0 ? cleanedQuestionParts : [{ part_desc: '', part_total_marks: '', part_guided_answer: [{ part_model_ans: '', part_answer_mark: '' }] }]; // 重置表单并设置处理后的初始值 formInput.resetFields(); formInput.setFieldsValue({ ...questionData, question_parts: finalQuestionParts }); } }, [isModalVisible, questionData]); return ( <> <Modal visible={isModalVisible} onCancel={() => { formInput.resetFields(); hideModal(); }} width={1200} footer={[ <Button key="back" onClick={() => { formInput.resetFields(); hideModal(); }}> 取消 </Button>, <Button key="submit" type="primary" onClick={() => { formInput.validateFields().then(values => { console.log('提交的数据:', values); // 这里替换成你的提交逻辑,比如dispatch action hideModal(); }).catch(errorInfo => { console.log('表单验证失败:', errorInfo); }); }}> 确认提交 </Button>, ]} > <Form layout='vertical' ref={(ref) => { formInput = ref }} name='dynamic_form_item' > <Form.List name='question_parts' key='question_parts'> {(fields, { add, remove }, { errors }) => ( <> {fields.map((field, index) => ( <Space key={field.key} direction='vertical' > <Form.Item key={`QuestionPart${index}`}> <Row> <Col span={10}> <div style={{ overflow: 'auto', height: 400, width: 590, }} > <Form.Item {...field} label={`Question Part ${index + 1} Description`} fieldKey={[field.fieldKey, 'part_desc']} name={[field.name, 'part_desc']} key={`part_desc${index}`} rules={[{ required: true, message: '请输入题目描述' }]} > <Input.TextArea rows={8} placeholder='Description' /> </Form.Item> <Form.Item {...field} label={`Question Part ${index + 1} Marks`} fieldKey={[field.fieldKey, 'part_total_marks']} name={[field.name, 'part_total_marks']} key={`part_total_marks${index}`} rules={[{ required: true, message: '请输入分数', type: 'number' }]} > <Input placeholder='Marks' style={{ border: '1px solid black', width: 450, }} /> </Form.Item> </div> </Col> <div className='vl'></div> <Col span={12} offset={2}> <div > <Form.List {...field} name='part_guided_answer' fieldKey={[field.fieldKey, 'part_guided_answer']} key={`part_guided_answer${index}`} > {(fields, { add, remove }, { errors }) => ( <> {fields.map((field, idx) => ( <Space key={field.key} direction='vertical' > <Form.Item key={`QuestionPartGuided${idx}`}> <Form.Item {...field} label={`Question Part Guided Answer ${idx + 1}`} fieldKey={[field.fieldKey, 'part_model_ans']} name={[field.name, 'part_model_ans']} key={`part_model_ans${idx}`} rules={[{ required: true, message: '请输入引导答案' }]} > <Input.TextArea rows={4} placeholder='Guided Answer' /> </Form.Item> <Form.Item {...field} label={`Question Part Guided Answer Marks ${idx + 1}`} fieldKey={[field.fieldKey, 'part_answer_mark']} name={[field.name, 'part_answer_mark']} key={`part_answer_mark${idx}`} rules={[{ required: true, message: '请输入引导答案分数', type: 'number' }]} > <Input placeholder='Guided Answer Marks' /> </Form.Item> <MinusCircleOutlined className='dynamic-delete-button' onClick={() => remove(field.name)} /> </Form.Item> </Space> ))} <Form.Item style={{ fontWeight: 'bold' }}> <Button type='dashed' onClick={() => add()} icon={<PlusOutlined />} > Add Question Part Guided Answer </Button> <Form.ErrorList errors={errors} /> </Form.Item> </> )} </Form.List> </div> </Col> <MinusCircleOutlined className='dynamic-delete-button' onClick={() => remove(field.name)} /> </Row> <div className='vr'></div> </Form.Item> </Space> ))} <Form.Item> <Button type='dashed' onClick={() => add()} icon={<PlusOutlined />} > Add Question Part </Button> <Form.ErrorList errors={errors} /> </Form.Item> </> )} </Form.List> </Form> </Modal> </> ) }; export default AddPartQuestionModalAgain;
关键修改点说明
- 空值过滤逻辑:在
useEffect里对question_parts进行过滤,只有当题目部分的描述、分数,或者其下的引导答案至少有一个有内容时,才保留该条目。 - 表单重置与初始化:监听
isModalVisible的变化,当模态框打开时,先重置表单再设置过滤后的初始值,确保每次打开都是干净的状态。 - 完善默认值结构:把
questionData的默认question_parts从['']改成符合实际结构的对象数组,避免类型不匹配导致的渲染问题。 - 添加表单验证:给必填字段加上验证规则,防止用户提交空内容。
内容的提问来源于stack exchange,提问作者IDon'tGetIt
相关产品推荐
相关产品推荐

