SoFunction
Updated on 2025-04-05

ant design vue dynamic loop generation form and detailed explanation of custom verification rules

In ant design vue development, sometimes we use background data to loop to generate forms, we need to bind props and custom verification events

The following is a summary written by me using the methods provided by the official website and combined with my own projects.

1. First define the form data in data

// Circularly generated personnel form dataaddManForm:{
    manObjList:[
        {
            person_info_company_guid:undefined,//Company            person_info_team_guid:undefined,//team            person_info_plan_sum:'',//Planned investment quantity            person_info_plan_time:undefined,//Plan to invest time            person_info_sum:'',//The actual amount of investment            person_info_time:undefined,//Actual time invested            person_info_remark:'',
            currentParentGuid:'',//The currently selected row is used to add the parent id        }
    ]
},

2. Loop in the dialog box to generate a form

<a-modal
	:title="addManTitle"
	:visible="manModalVisible"
	@ok="manModalOk"
	@cancel="manModalCancel"
	okText="Sure"
	cancelText="Cancel"
	:mask=false
	:zIndex=1000
	:width=850>
	    <a-form-model ref="addManFormRef" :model="addManForm" :label-col="{span:7}" :wrapper-col="{ span: 16 }">
	        <a-row>
	        </a-row>
	        <div class="manContent">
	            <div class="manSingle" v-for="(item,index) in " :key="index">
	                <div class="title">
	                    <div class="iconOperate">
	                        <a-icon type="up"  v-if="manArrowState && index==0" @click="manFold"/>
	                        <a-icon type="down" v-if="!manArrowState && index==0"  @click="manUnfold"/>
	                        <i class="iconfont iconicon-test" v-if="!btnVisible && index==0" @click="addManObjList"></i>
	                        <i class="iconfont iconshanchu" v-if="!btnVisible && index==0" @click="delManObjList"></i>
	                    </div>
	                </div>
	                <div class="manContainer">
	                    <a-row>
	                        <a-col :span="12">
	                            <a-form-model-item label="Company:" :prop="'manObjList.'+index+'.person_info_company_guid'"
	                                :rules="[{ required: true, message: 'The company you belong to cannot be empty', trigger: 'change'}]">
	                                <a-tree-select
	                                    v-model="item.person_info_company_guid"
	                                    :tree-data="companySelectData"
	                                    style="width:100%"
	                                    placeholder="Please select the company"
	                                    allow-clear
	                                    :disabled="modalDisabled"
	                                    tree-default-expand-all/>
	                            </a-form-model-item>
	                        </a-col>
	                        <a-col :span="12">
	                            <a-form-model-item label="Team:"  :prop="'manObjList.'+index+'.person_info_team_guid'"
	                                :rules="[{ required: true, message: 'The team cannot be empty', trigger: 'change'}]">
	                                <a-tree-select
	                                    v-model="item.person_info_team_guid"
	                                    :tree-data="teamSelectData"
	                                    style="width:100%"
	                                    placeholder="Please select the team"
	                                    allow-clear
	                                    :disabled="modalDisabled"
	                                    tree-default-expand-all/>
	                            </a-form-model-item>
	                        </a-col>
	                    </a-row>
	                    <a-row>
	                        <a-col :span="12">
	                            <a-form-model-item label="Planned investment quantity:"  :prop="'manObjList.'+index+'.person_info_plan_sum'"
	                                :rules="[{type: 'number', message: 'Only input numbers are supported', trigger: 'blur' ,transform(value){ 
	                                    if(value){
	                                        // Convert the entered value to a number	                                        var val = Number(value)
	                                        if(/^(?!0+(?:\.0+)?$)(?:[1-9]\d*|0)(?:\.\d{1,2})?$/.test(val)) return val
	                                        // Returning false means verification failure	                                        return false
	                                    }
	                                }},
	                                {required:true,message:'The planned investment cannot be empty',trigger: 'blur'}]">
	                                <a-input v-model="item.person_info_plan_sum" :disabled="modalDisabled" placeholder="Please enter the planned investment quantity" />
	                            </a-form-model-item>
	                        </a-col>
	                        <a-col :span="12">
	                            <a-form-model-item label="Planned to invest time:" :prop="'manObjList.'+index+'.person_info_plan_time'"
	                                :rules="[{ required: true, message: 'The planned investment time cannot be empty', trigger: 'change'},
	                                {validator:manPlanTime}]">
	                                <a-date-picker v-model="item.person_info_plan_time" format="YYYY-MM-DD" :disabled="modalDisabled" style="width:100%"/>
	                            </a-form-model-item>
	                        </a-col>
	                    </a-row>
	                    <a-row>
	                        <a-col :span="12">
	                            <a-form-model-item label="Real investment quantity:"  :prop="'manObjList.'+index+'.person_info_sum'"
	                                :rules="[{type: 'number', message: 'Only input numbers are supported', trigger: 'blur' ,transform(value){ 
	                                    if(value){
	                                        // Convert the entered value to a number	                                        var val = Number(value)
	                                        if(/^(?!0+(?:\.0+)?$)(?:[1-9]\d*|0)(?:\.\d{1,2})?$/.test(val)) return val
	                                        // Returning false means verification failure	                                        return false
	                                    }
	                                }},
	                                {required:true,message:'The actual amount of investment cannot be empty',trigger: 'blur'}
	                            ]">
	                                <a-input v-model="item.person_info_sum" :disabled="modalDisabled" placeholder="Please enter the actual amount of investment"/>
	                            </a-form-model-item>
	                        </a-col>
	                        <a-col :span="12">
	                            <a-form-model-item label="Real invested time:" :prop="'manObjList.'+index+'.person_info_time'"
	                                :rules="[{ required: true, message: 'The actual time invested cannot be empty', trigger: 'change'},
	                                {validator:manActualTime}]" >
	                                <a-date-picker v-model="item.person_info_time" placeholder="Please select the actual time invested" style="width:100%" :disabled="modalDisabled"/>
	                            </a-form-model-item>
	                        </a-col>
	                    </a-row>
	                    <a-row>
	                        <a-col :span="12">
	                            <a-form-model-item label="Remark:"  :prop="'manObjList.'+index+'.person_info_remark'"
	                            :rules="[{max: 200, message: 'Remarks length cannot be greater than 200', trigger: 'blur' }]">
	                                <a-input type="textarea" v-model="item.person_info_remark" placeholder="Please enter a note" :disabled="modalDisabled"/>
	                            </a-form-model-item>
	                        </a-col>
	                    </a-row>
	                </div>
	            </div>
	        </div>
	    </a-form-model>
	</a-modal>

fold and unfold methods control expansion and collapse, addManObjList adds a set of data, delManObjList deletes a set of data

Note:Prop should be bound dynamically, array + index + field name =>manObjList.’+index+’.person_info_remark’

3. Add data method

// Add a person information formaddManObjList(){
    ( {
        person_info_company_guid:undefined,//Company        person_info_team_guid:undefined,//team        person_info_plan_sum:'',//Planned investment quantity        person_info_plan_time:undefined,//Plan to invest time        person_info_sum:'',//The actual amount of investment        person_info_time:undefined,//Actual time invested        man_deviation_number:'',//Deviation of investment quantity        man_deviation_time:'',//Deficiency of investment time        person_info_remark:'',
        currentParentGuid:'',//The currently selected row is used to add the parent id    })
},

Custom verification in loop form

Bind dynamic rules in a-form-model-item

:rules="[
	{required: true, message: 'The planned investment time cannot be empty', trigger: 'change'},
	{validator:manPlanTime}
]"
// Personnel verification rules, planning timemanPlanTime(rule,value,callback){
    let planTimeArr = (item=>{
        return item.person_info_plan_time == value
    })
    if(value && planTimeArr[0].person_info_time){
        if(this.$moment(value).format('YYYY-MM-DD') > this.$moment(planTimeArr[0].person_info_time).format('YYYY-MM-DD')){
            callback(new Error('The planned investment time shall not be greater than the actual investment time'))
            return false
        }
        callback()
    }
    callback()
},

Written at the end

This will complete a loop to generate the form and complete custom form verification, but there is a small flaw. The dynamically generated date selection box is bound to the date in UTC format, rather than the date format of the moment object bound to the component itself.

The above is personal experience. I hope you can give you a reference and I hope you can support me more.