el-autocomplete 必填校验问题

需求描述

  • 表单中,权限编号是远程搜索组件 el-autocomplete,该组件绑定值为 String 类型
  • 提交时,业务需求需要传递权限编号整个对象的值,包括 fetchIdfetchName
  • 因此需要监听 el-autocomplete 的选择事件,拿到选择的对象,赋值给提交参数
    在这里插入图片描述

初步逻辑

<el-form ref="form" :model="form" label-width="80px" :rules="rules" class="form">
  <el-form-item label="姓名" prop="inputText">
    <el-input v-model="form.inputText" placeholder="请输入内容"></el-input>
  </el-form-item>
  <el-form-item label="居住地" prop="selectVal">
    <el-select v-model="form.selectVal" placeholder="请选择">
      <el-option
        v-for="item in options"
        :key="item.value"
        :label="item.label"
        :value="item"
        value-key="value"
      >
      </el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="权限编号" prop="fetchVal">
    <el-autocomplete
      v-model="form.fetchValFilter"
      placeholder="请输入内容"
      @select="handleSelect"
      :fetch-suggestions="querySearchAsync"
      value-key="fetchName"
    ></el-autocomplete>
  </el-form-item>
  <el-button type="primary" @click="onSubmit">提交</el-button>
</el-form>
  • 远程搜索方法,模拟接口
// 远程搜索方法
querySearchAsync(searchText, cb) {
  console.log("远程搜索输入内容", searchText);
  this.form.fetchVal = {};
  // 模拟接口
  setTimeout(() => {
    let result = [];
    for (var i = 0; i < 10; i++) {
      result.push({
        fetchId: (i + 1) * 1,
        fetchName: "12345_" + (i + 1) * 1,
      });
    }
    console.log("远程搜索获取到的列表", result);
    cb(result);
  }, 300);
},
  • 监听到的远程搜索的选择事件
// 选中远程搜索列表的值
handleSelect(item) {
   console.log("选择的对象", item);
   this.form.fetchVal = item;
},
  • rules 中,关于远程搜索的校验,应该是判断 this.form.fetchVal 对象中是否包含 fetchIdfetchName
rules: {
  inputText: [{ required: true, message: "请填写内容", trigger: "blur" }],
  selectVal: [
    {
      required: true,
      validator: (rule, value, callback) => {
        if (this.form.selectVal && this.form.selectVal.value) {
          callback();
        } else {
          callback(new Error("请选择内容"));
        }
      },
      trigger: "change",
    },
  ],
  fetchVal: [
    {
      required: true,
      validator: (rule, value, callback) => {
        console.log("change 事件被触发,开启校验");
        console.log("校验的是对象");
        if (this.form.fetchVal && this.form.fetchVal.fetchId) {
          callback();
        } else {
          callback(new Error("请选择内容"));
        }
      },
      trigger: "change",
    },
  ],
},

问题出现

  • 校验表单时,如果 el-autocomplete 的触发为 change,则在输入的过程中,就会触发。此时还未执行 select 事件,this.form.fetchVal 为空对象,则会进入到校验抛错的判断中
    在这里插入图片描述
  • 校验表单时,如果 el-autocomplete 的触发为 blur,在选中结果后,会先触发 blur 事件,后触发 select 事件,依旧拿不到 this.form.fetchVal ,会进入到校验抛错的判断中
fetchVal: [
  {
    required: true,
    validator: (rule, value, callback) => {
      console.log("blur 事件被触发,开启校验");
      console.log("this.form.fetchVal", this.form.fetchVal);
      if (this.form.fetchVal && this.form.fetchVal.fetchId) {
        callback();
      } else {
        callback(new Error("请选择内容"));
      }
    },
    trigger: "blur",
  },
],

在这里插入图片描述

解决方式

方法一:延时操作

  • blur 会比 select 先触发,那么添加定时器,做一个延时,可以手动将判断放到 select 事件的后面
fetchVal: [
 {
   required: true,
   validator: (rule, value, callback) => {
     console.log("blur 事件被触发");
     console.log("this.form.fetchVal", this.form.fetchVal);
     setTimeout(() => {
       console.log('此时才开启校验');
       console.log("this.form.fetchVal", this.form.fetchVal);
       if (this.form.fetchVal && this.form.fetchVal.fetchId) {
         callback();
       } else {
         callback(new Error("请选择内容"));
       }
     }, 200);
   },
   trigger: "blur",
 },
],

在这里插入图片描述

方法二:手动控制触发校验的方式

  • 移除 rules 中的校验,在提交校验之前,为当前项添加校验规则。或者在选中结果后为当前项添加校验规则,之后校验此项
// 选中远程搜索列表的值
handleSelect(item) {
  this.form.fetchVal = item;
  // 添加校验规则
  this.$refs.form.rules.fetchVal[0].validator = (rule, value, callback) => {
    if (this.form.fetchVal && this.form.fetchVal.fetchId) {
      callback();
    } else {
      callback(new Error("请选择内容"));
    }
  };
  // 对当前项进行校验
  this.$refs.form.validateField("fetchVal", (valid) => {
    if (valid) {
      console.log("对当前项进行校验-校验通过了");
    }
  });
},
// 提交
onSubmit() {
  console.log("form", this.form);
  // 添加校验规则
  this.$refs.form.rules.fetchVal[0].validator = (rule, value, callback) => {
    if (this.form.fetchVal && this.form.fetchVal.fetchId) {
      callback();
    } else {
      callback(new Error("请选择内容"));
    }
  };
  // 开启校验
  this.$refs.form.validate((valid) => {
    if (valid) {
      console.log("整个表单进行校验-校验通过了");
    }
  });
},

完整代码

export default {
  data() {
    return {
      form: {
        inputText: "",
        selectVal: {},
        fetchVal: {}, // 远程搜索获取的对象
        fetchValFilter: "", // 远程搜索输入值
      },
      rules: {
        inputText: [{ required: true, message: "请填写内容", trigger: "blur" }],
        selectVal: [
          {
            required: true,
            validator: (rule, value, callback) => {
              if (this.form.selectVal && this.form.selectVal.value) {
                callback();
              } else {
                callback(new Error("请选择内容"));
              }
            },
            trigger: "change",
          },
        ],
        fetchVal: [
          {
            required: true,
            validator: (rule, value, callback) => {},
            trigger: "blur",
          },
        ],
      },
      options: [
        { label: "北京", value: 1 },
        { label: "天津", value: 2 },
        { label: "上海", value: 3 },
        { label: "重庆", value: 4 },
      ],
    };
  },
  mounted() {},
  methods: {
    // 远程搜索方法
    querySearchAsync(searchText, cb) {
      console.log("远程搜索输入内容", searchText);
      this.form.fetchVal = {};
      // 模拟接口
      setTimeout(() => {
        let result = [];
        for (var i = 0; i < 10; i++) {
          result.push({
            fetchId: (i + 1) * 1,
            fetchName: "12345_" + (i + 1) * 1,
          });
        }
        console.log("远程搜索获取到的列表", result);
        cb(result);
      }, 300);
    },
    // 选中远程搜索列表的值
    handleSelect(item) {
      this.form.fetchVal = item;
      // 添加校验规则
      this.$refs.form.rules.fetchVal[0].validator = (rule, value, callback) => {
        if (this.form.fetchVal && this.form.fetchVal.fetchId) {
          callback();
        } else {
          callback(new Error("请选择内容"));
        }
      };
      // 对当前项进行校验
      this.$refs.form.validateField("fetchVal");
    },
    // 提交
    onSubmit() {
      console.log("form", this.form);
      // 添加校验规则
      this.$refs.form.rules.fetchVal[0].validator = (rule, value, callback) => {
        if (this.form.fetchVal && this.form.fetchVal.fetchId) {
          callback();
        } else {
          callback(new Error("请选择内容"));
        }
      };
      // 开启校验
      this.$refs.form.validate((valid) => {
        if (valid) {
          console.log("整个表单进行校验-校验通过了");
        }
      });
    },
  },
};
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值