Element UI 針對循環表單嵌套表格校驗 解決方式


最近有一個分單的需求,需要把一個二維數組通過表單提交傳參給后台。

主要數據格式(數組[對象{對象,數組},對象{對象,數組}])示例 this.ruleList:

[{
            info: {
                name: '1',
                paymentTerm: '',
                stockPosition: '',
                purchaseGroup: '',
            },
            materialList: [{
                    a: '',
                    b: '',
                    deliveryDate: '2022-3-20'
                },
                {
                    a: '',
                    b: '',
                    deliveryDate: '2022-3-20'
                }
            ]
        },
        {
            info: {
                name: '2',
                paymentTerm: '',
                stockPosition: '',
                purchaseGroup: '',
            },
            materialList: [{
                a: '',
                b: '',
                deliveryDate: '2022-3-20'
            }]
        }
    ]

數據處理部分代碼示例:

this.ruleDataList.forEach(item=>{
                    this.$set(item.info,'materialList',item.materialList);
                    item.materialList.forEach(ele=>{
                        this.$set(ele,'defaultDate',ele.deliveryDate);
                        this.$set(ele,'rule',[
                            {
                                required: true,
                                validator:(rule, value, callback)=>{
                                    this.deliveryDate(rule,callback,ele.defaultDate,ele.deliveryDate)
                                },
                                trigger: ['blur','change']
                            }
                        ])
                    })
                    this.validateList.push(item.info)
                })

首先將this.ruleDataList 里的對象和數組都合並到info里,materialList數組里新增了兩個屬性值rule和defaultDate並push到一個新數組validateList里,這樣我們就得到this.validateList的數據格式為:

{
            name: '1',
            paymentTerm: '',
            stockPosition: '',
            purchaseGroup: '',
            materialList: [{
                    a: '',
                    b: '',
                    deliveryDate: '2022-3-20',
                    rule: '表格項校驗規則'
                },
                {
                    a: '',
                    b: '',
                    deliveryDate: '2022-3-20',
                    rule: '表格項校驗規則'
                }
            ]
        },
        {
            name: '2',
            paymentTerm: '',
            stockPosition: '',
            purchaseGroup: '',
        materialList: [{
            a: '',
            b: '',
            deliveryDate: '2022-3-20',
            rule: '表格項校驗規則'
        }]
    }
]

這樣我們渲染頁面時就可以直接用處理后的數組,更方便表單的校驗。頁面通過v-for來循環validateList,獲得多個表單,所以表單的ref拼接了索引,頁面代碼示例如下:

<div class="separateContent">
                <el-row class="soDetailRow" v-for="(item,index) in validateList" :key="index">
                    <div class="subTitle">
                        <span>{{item.supplierName}}</span>
                    </div>
                    <el-form :model="item" :ref="'ruleForm'+index" label-width="100px">
                        <el-form-item label="付款條件:" prop="paymentTerm"
                            :rules="[{ required: true, message: '付款條件不能為空'}]"
                            class="formRow">
                            <el-select placeholder="請選擇"
                                filterable
                                style="width:200px;margin-right:10px"
                                v-model="item.paymentTerm">
                                <el-option v-for="ops in paymentClauseList"
                                    :key="ops.value"
                                    :label="ops.label"
                                    :value="ops.value">
                                </el-option>
                            </el-select>
                        </el-form-item>
                   
                        <el-table 
                            border 
                            :row-class-name="tableRowClassName"
                            :header-cell-style="{background: '#f7f7f7',padding:'5px 10px'}"
                            ref="multipleTable"
                            :data="item.materialList">
                            <el-table-column align="center" prop="orderUnitDesc" label="單位" ></el-table-column>
                            <el-table-column align="center" prop="deliveryDate" label="交貨期" min-width="130px">
                                <template slot-scope="scope">
                                    <el-form-item 
                                        :prop="'materialList.'+scope.$index+'.deliveryDate'"
                                        :rules="scope.row.rule"
                                        class="costValue">
                                        <el-date-picker
                                            :clearable="false"
                                            style="width:130px"
                                            @change="handleChangeDate(scope.row,`materialList.${scope.$index}.deliveryDate`,`${index}`,)"
                                            v-model="scope.row.deliveryDate"
                                            type="date"
                                            value-format="yyyy-MM-dd"
                                            :placeholder="`選擇日期${index}`">
                                            </el-date-picker>
                                    </el-form-item>
                                </template>
                            </el-table-column>
                        </el-table>
                    </el-form>
                </el-row>
            </div>
            <el-row class="crumbs btns printBtns" type="flex" justify="center">
                <el-button  class="el-btn" @click="hanldeCheckForm('1')"  v-preventReClick>存為待推送</el-button>
                <el-button type="primary"  class="el-btn" @click="hanldeCheckForm('2')"  v-preventReClick>確認分單</el-button>
            </el-row>

由於表單是多個,表單里嵌套的表格也是多個,根據prop定義的動態表單校驗會有重復值,所以在處理數組時,set了每一項的自定義校驗規則(每項的交貨期日期組件選擇都不能小於默認日期),規則代碼如下:

  // 自定義日期校驗
        deliveryDate(rule, callback,defaultDate,deliveryDate){
            let index = Number(rule.field.split('.')[1])//獲取當前驗證項的index,對應數據的index
            if(!deliveryDate){
                callback(new Error('交貨日期不能為空'))
            }else if(defaultDate > deliveryDate){
                callback(new Error('只能選擇'+ defaultDate +'之后的日期'))
            }else{
                callback()
            }
        },

表單提交時,由於是多個表單,只有所有的表單校驗通過之后再去請求接口,這里用到的是Promise.all的方法,代碼示例如下:

// 表單校驗
        hanldeCheckForm(type){
            let _self = this;
            let newArr = [];
            this.validateList.forEach((item,index)=>{
                let  result = new Promise(function(resolve, reject) {
                    _self.$refs['ruleForm'+index][0].validate(valid=>{
                            if (valid) {
                                resolve();
                            } else { reject() }
                        })
                    })
                newArr.push(result);
            })
            
            Promise.all(newArr).then(function() { //都通過了
                let paramsList = [];
                _self.validateList.forEach(item=>{
                    paramsList.push({info:item,materialList:item.materialList})
                })
                if(type == '1'){
                    _self.handlePushClick(paramsList)
                }else{
                    _self.handleConfirmClick(paramsList)
                }   
            }).catch(function(err) {
                console.log(err);
            })
        },
        // 待推送
        handlePushClick(params){
            saveWaitPush(params).then(res=>{
                if(res.code == '200'){
                    this.$message({
                        message: '操作成功',
                        type: 'success'
                    });
                    this.$emit('handleClose',false,true)
                }
            })
        },
        // 待確認
        handleConfirmClick(params){
            confirmSplit(params).then(res=>{
                if(res.code == '200'){
                    this.$message({
                        message: '操作成功',
                        type: 'success'
                    });
                    this.$emit('handleClose',false,true)
                }
            })
        },

由於后台要求入參格式跟未處理之前一致,所以在接口請求之前又重新將對象和數據剝離成 paramsList.push({info:item,materialList:item.materialList})。這里沒有專門對info里的materialList做刪除處理,可以自行刪除。

解決需求痛點:

1.循環(多)表單動態校驗。

2.自定義校驗傳參validator入參無法接收rule, value, callback 之外的參數,導致表格項校驗時,無法直接通過索引值獲取數組里的某一項做校驗,曲線救國通過set以及在validator 通過自定義方法專門對入參做處理。


免責聲明!

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



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