Vue3+Element Plus动态校验多个form表单+table表格行内元素比较大小

342 阅读1分钟

在做项目的时候难免会遇到各种复杂的表单校验,之前也遇到过这种类似的问题,这次就来总结一下,便于以后可以提高工作效率,看标题可能不太理解具体是什么功能,下面用图来解释一下:

image.png

如上图所示:可以动态添加/删除form表单以及table行,并且需要比较table每行“销售价格”和“市场价格”的大小进行表单校验。

实现方式有两种:

第一种方式:

实现思路:将<el-form>标签放在最外层,只使用一个formRef,每个<el-form-item>中的props都使用formList.0.table.0.orderSn这种方式,例如:

<el-form ref="formRef" :model="formData" label-width="100px" :inline="true">
  <el-container v-for="(item, index) in formData.formList" :key="index">
    ...
    <el-form-item :prop="`formList.${index}.table.${$index}.orderSn`" :rules="tableRules.orderSn">
  </el-container>
</el-form>

主要难点是如何比较table行内元素的大小(例:销售价、市场价),这里可以根据rule可以获取到formListtable两个数组的键值index

image.png

写法如下:

const salePriceValidate = (rule, value, callback) => {
  const indexs = rule.field.match(/\d+/g)
  const marketPrice = formData.value.formList[indexs[0]].table[indexs[1]].marketPrice
  if (value && marketPrice && value > marketPrice) {
    callback(new Error('不能大于市场价格'));
  } else {
    callback();
  }
}
salePrice: [
  { required: true, message: '请输入销售价格', trigger: 'blur' },
  { validator: salePriceValidate, trigger: 'blur' }
],

完整代码:

第二种方式:

实现思路:在<el-form>外层进行v-for,根据formList数组定义多个formRef,form提交时需要for循环校验每个form,写法如下:

<el-container v-for="(item, index) in formList" :key="index">
  <el-form :ref="(el) => formRefs[index] = el" :rules="formRules"></el-form>
</el-container>
const submit = async () => {
  try {
    const promises = formRefs.value.map(item => item && item.validate())
    const results = Promise.all(promises)
    if ((await results).every(res => res)) {
      console.log(formList.value, '---formList')
    }
  } catch (error) {
    console.log(error, '---err')
  }
}

主要难点:还是如何比较table行内元素的大小(例:销售价、市场价),这里就不能用rule.field来获取键值了,可以通过:rules="tableRules(row)"传参处理,写法如下:

<el-form-item :prop="`table.${$index}.marketPrice`" :rules="tableRules(item.table[$index]).marketPrice"></el-form-item>
const salePriceValidate = (row) => {
  return (rule, value, callback) => {
    if (value && row.marketPrice && value > row.marketPrice) {
      callback(new Error('不能大于市场价格'));
    } else {
      callback();
    }
  }
}
const tableRules = (row) => {
  return {
    salePrice: [
      { required: true, message: '请输入销售价格', trigger: 'blur' },
      { validator: salePriceValidate(row), trigger: 'blur' }
    ],
  }
}

完整代码: