antd+vue3實現動態表單的自動校驗


由於vue3用的人還不多,所以有些問題博主踩了坑只能自己爬出來了,特此做個記錄。如有錯誤,請大家指正。

  回歸正題,我所做的業務是,動態添加表單項,對每一項單獨做校驗,效果如下:

  

 

  主要代碼如下:

 1 <a-form
 2     name="custom-validation"
 3     ref="formRef"
 4     :model="modelRef"
 5     :rules="rules"
 6     v-bind="layout"
 7     @finish="handleFinish"
 8     @finishFailed="handleFinishFailed"
 9   >
10     <div class="card-box">
11       <div class="card-head">基礎信息</div>
12       <div class="card-body">
13         <a-form-item label="食材名稱" name="name">
14           <a-input v-model:value="modelRef.name" autocomplete="off" />
15         </a-form-item>
16         <a-form-item label="食材編號" name="foodNumber">
17           <a-input v-model:value="modelRef.foodNumber" autocomplete="off" />
18         </a-form-item>
19         <a-form-item label="食材類型" name="foodType">
20           <a-select v-model:value="modelRef.foodType" placeholder="">
21             <a-select-option value="shanghai">Zone one</a-select-option>
22             <a-select-option value="beijing">Zone two</a-select-option>
23           </a-select>
24         </a-form-item>
25         <a-form-item label="食材產地" name="birthplace">
26           <a-input v-model:value="modelRef.birthplace" autocomplete="off" />
27         </a-form-item>
28       </div>
29     </div>
30     <div class="card-box">
31       <div class="card-head">營養成分信息</div>
32       <div class="card-body">
33         <a-button primary shape="round" @click="onAdd">
34           <PlusSquareOutlined /> 新增
35         </a-button>
36         <div class="nutrients-content-box">
37           <a-row type="flex" justify="space-between" align="middle">
38             <a-col :span="5" v-for="(item,index) in modelRef.nutrients" :key="index">
39               <div class="nutrients-input-box card-box">
40                 <div>{{item.name}}</div>
41                 <div class="flex-align-end">
42                   <div>
             注:form.item的name必須與modelRef里面的字段保持一致,否則無法實現自動校驗,所以此處name使用動態數據,
          當數組nutrients值改變時,就往modelRef里面加字段(與這里的name保持一致)。下面代碼有說明
43 <a-form-item :name="item.id+'nutrients'"

                     當name設置成功了,此處的規則便會在change觸發后執行 44 :rules="[{validator: validateNutrients, trigger: 'change'}]"> 45 <a-input v-model:value="item.value" @change="onFieldChange(item)"/> 46 </a-form-item> 47 </div> 48 <span>{{item.unit}}</span> 49 </div> 50 </div> 51 </a-col> 52 </a-row> 53 </div> 54 </div> 55 </div> 56 <div class="op-btn-box"> 57 <a-form-item :wrapper-col="{ span: 12, offset: 18 }"> 58 <a-button>取消</a-button> 59 <a-button type="primary" style="margin-left: 10px" html-type="submit">保存</a-button> 60 </a-form-item> 61 </div> 62 </a-form>
 1 import { onMounted, reactive, toRefs, watch } from 'vue'
 2 setup() {
    //表單校驗里的name值必須與此處的字段保持一致
3 const modelRef = reactive({ 4 name: '', 5 foodNumber: '', 6 foodType: null, 7 birthplace: '', 8 nutrients: [], 9 }) 10 const layout = { 11 labelCol: { span: 2 }, 12 wrapperCol: { span: 6 }, 13 }
    //此處為動態表單的自定義規則
14 const validateNutrients = async (rule, value) => { 15 if (!value) { 16 return Promise.reject(new Error('請輸入數值')) 17 } 18 const numReg = /^(?!0+(?:\.0+)?$)(?:[1-9]\d*|0)(?:\.\d{1,2})?$/ 19 if (!numReg.exec(value)) { 20 return Promise.reject(new Error('請輸入正確數字')) 21 } 22 } 23
    //其他普通的校驗,可做統一處理 24 const rules = { 25 name: [ 26 { required: true, message: '請輸入食材名稱', trigger: 'change' }, 27 { max: 20, message: '最多輸入20字', trigger: 'change' }, 28 ], 29 foodNumber: [ 30 { required: true, message: '請輸入食材編號', trigger: 'change' }, 31 { max: 20, message: '最多輸入20字', trigger: 'change' }, 32 ], 33 foodType: [ 34 { required: true, message: '請選擇食材類型', trigger: 'change' }, 35 ], 36 birthplace: [ 37 { required: true, message: '請輸入食材產地', trigger: 'change' }, 38 { max: 20, message: '最多輸入20字', trigger: 'change' }, 39 ], 40 } 41
    //此處是關鍵,modelRef.nutrients是遍歷動態表單所用的數組,當數組值改變時,往modelRef里面加字段,與上面的動態循環出來的form.item的name保持一致 42 watch( 43 () => modelRef.nutrients, 44 val => { 45 if (val.length) { 46 val.forEach(item => { 47 modelRef[`${item.id}nutrients`] = item.value 48 }) 49 } 50 }, 51 ) 52 /* 提交保存 */ 53 const handleFinish = (values) => { 54 console.log(values) 55 } 56 const handleFinishFailed = (errors) => { 57 console.log(errors) 58 }
   //輸入框的值改變時,需要更新modelRef里動態添加的字段的值,否則校驗會出錯。
59 const onFieldChange = (item) => { 60 modelRef[`${item.id}nutrients`] = item.value 61 } 62 63 return { 64 ...toRefs(state), 65 modelRef, 66 rules, 67 layout, 68 handleFinish, 69 handleFinishFailed, 70 validateNutrients, 71 onFieldChange, 72 } 73 },

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM