背景:

每个模块的数据是调取后端接口获取的,有数据则展示对应模块。每个模块内的表格都可以修改出价,不同类型的数据出价范围也不一样,需要进行校验。在保存设置的时候,校验成功才提交,否则阻断。

思路:

第一次是给每个模块内的表格的el-input绑定blur事件,如果输入值的范围不对,则弹出message消息提示,最后在保存设置的时候遍历所有数据,如果值不对则提示且阻断。这种方法会导致当在修改完某个值直接点提交则会触发两次提示,体验不好。

第二次改为表单校验,提示更加友好美观,体验也更流畅,符合产品要求。

以下展示第二种效果以及分享写法。

最终效果:

写法:

1、html部分:这里的html结构是一个el-form里面嵌套el-table,el-table再嵌套表单项el-form-item。

注意:

  • 需要给每个表单绑定不同的ref,保存将根据ref对应的表单进行校验
  • 因为嵌套关系,el-table的数据绑定的是:data="formData.costControlList"
  • 表格中的表单项校验需要绑定prop字段,这个字段根据表格索引动态绑定,将要校验的字段在表格数据中对应。写法为
    :prop="`costControlList.${scope.$index}.priceNext`" 
  •  校验规则可以在el-form上一次性传递,也可以在单个的表单域上传递属性的验证规则。因为我有多个表单,每个表单只有一项需要校验,所以我采用后一种方式。写法为
    :rules="[{ required: true, message: '请输入'},
    { required: true, validator: (rule, value, callback,type) => costValidator(rule, value, callback,scope.row.constraintType)}]">

    解释:动态绑定一个数组,第一条为必填校验,第二条为自定义校验规则,因为我这个校验还需要根据不同的类型来判断范围,所以我需要多传递一个类型参数。如果不需要这样判断,直接调用校验方法即可。

完整html代码如下:

<el-form ref="costForm" :model="formData">
    <el-table :data="formData.costControlList" ref="costTable" max-height="400">
        <el-table-column label="xx" prop="xx"></el-table-column>
        <el-table-column label="xx" prop="xx"></el-table-column>
        <el-table-column prop="xx" label="xx"></el-table-column>
        <el-table-column prop="priceNext" label="修改xx">
            <template v-slot="scope">
                <el-form-item :prop="`costControlList.${scope.$index}.priceNext`" 
                   :rules="[{required: true, message: '请输入'},
                    {required:true, validator: 
                    (rule, value, callback,type) => costValidator(rule, value, callback,scope.row.constraintType)}]">
                    <el-input v-model.trim="scope.row.priceNext"
                        @keyup.native="handleNumberType"
                        style="width: 250px"
                        placeholder="请输入"></el-input>
                 </el-form-item>
             </template>
        </el-table-column>
    </el-table>
</el-form>

2、自定义校验规则

costValidator(rule, value, callback,type) {
    if(type==='conv') {
        if(value < 3 || value > 9999.99) {
            callback('请输入3-9999.99的数字')
        }
    }else if(type==='click') {
        if(value < 0.05 || value > 99.99) {
            callback('请输入0.05-99.99的数字')
        }
    }
    callback()
},

3、提交行为

  • 利用promise封装一个验证表单的函数,如果表单不存在或者校验通过,则resolve,否则reject,将返回的结果添加到一个数组。
  • 点击保存时,循环校验每个表单,利用promise的all方法,如果校验全部通过则处理数据调取接口,不通过则会报错。

代码如下: 

checkForm(formName){  //封装验证表单的函数
    var result = new Promise((resolve,reject) => { 
        if(!this.$refs[formName]) {
            resolve();
        }else {
            this.$refs[formName].validate((valid) => {     
                if(valid) {
                    resolve();
                } else { 
                    reject() 
                  }
            })
        }
    })
    this.resultArr.push(result)  //把promise得到的结果push进数组保存
},
handleSave() {
    this.resultArr = []
    let formArr = ['costForm','roiForm','crowdForm']
    let tempArray = []
    formArr.forEach(item => {  // 根据表单的ref校验
        this.checkForm(item)
    })
    Promise.all(this.resultArr).then(response => {   
        let totalArray = this.formData.costControlList.concat(this.formData.roiControlList).concat(this.formData.customBidList)
        tempArray = totalArray.map(item => {
            if(item.crowdList.length) {
                item.crowdListTemp = item.crowdList.map(p=>{
                    return {
                        crowdId: p.crowdId,
                        bidPrice: p.priceNext,
                     }
                 })
            }
            return {
                campaignId: item.campaignId,
                bidType: item.bidType,
                constraintType: item.constraintType,
                constraintValue: item.priceNext, //修改后的出价
                crowdList: item.crowdListTemp || []
            }
        })
        this.loading = true;
        this.$axios.post('xxxx', {
            bizCode: this.bizCode,
            bidPriceList: tempArray
        }).then(response => {
            this.loading = false;
            if(response.data.status === 0) {
                  this.$message.success('修改成功');
                  this.$emit("close",true)
            }
        })
    }).catch(
        console.log("error")
    )
},
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐