31

el-form-item、a-form-model-item实现多个input、select关联校验

 3 years ago
source link: https://www.daozhao.com/9901.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

有时候我们有一个表单里面的表单项除了简单的校验,还有些之间的关联校验,比如两个数字型的最大值和最小值,我们还要校验最大值不能小于最小值。

el-form-item

<el-form :model="dataForm" :rules="rules">
      <el-form-item prop="number">
        最小值<el-input-number v-model="dataForm.min"></el-input-number>
      </el-form-item>
      <el-form-item prop="number">
        最大值<el-input-number v-model="dataForm.max"></el-input-number>
      </el-form-item>
      <el-form-item>
        <el-select v-model="dataForm.type" clearable>
          <el-option :value="1" label="第一个"></el-option>
          <el-option :value="2" label="第二个"></el-option>
        </el-select>
      </el-form-item>
    </el-form>

大家可以看到在最大值和最小值里面的prop上面写的时number,所以她们用的校验就是 rules.number 。所以现在我们就看看 rules 里面怎么写的。

export default {
  name: 'asyncValidate',
  data() {
    return {
      dataForm: {
        min: '',
        max: '',
        type: '',
      },
      rules: {
        number: [
          {
            validator: (rule, value, callback) => {
              if (this.dataForm.max >= this.dataForm.min) {
                callback();
              } else {
                callback(new Error('最大值不能小于最小值'));
              }
            },
            trigger: ['blur', 'change']
          },
        ],
      },
    };
  },
};

对于最大值和最小值两个formItem,我们没有分别使用 dataForm.maxdataForm.min ,而是组合使用。 比如我们在最小值输入2后会出现这样的校验信息

MN7JBve.png!mobile 我们可能更希望在修改了最小值导致最大、小值不合法时,最小值和最大值都会出现相应的校验提示信息。

我们再在最大值里面输入1后才会变成这样

QBbyA3Z.png!mobile

类似的,如果我们再次调整最大值为合法值3时,会变成这样

MNb6zeE.png!mobile

最大值的校验提示信息消失了,这是合理的,但是最小值的校验提示信息没有对应的消失,这显得不够合理了。

我们更希望最大、小值的校验信息能同步,不合法时给予提示,合法时提示消失。

目前我们触发校验的方式是输入框blur时触发校验,或者是点击+-符号来通过change触发校验。我们可以想办法让最大值输入框blur时自身会进行校验时还能够通知最小值进行校验,怎么实现呢?

...
<el-form-item prop="number" ref="minRef">
        最小值<el-input-number v-model="dataForm.min" @blur="onBlur('maxRef')" @change="onChange('maxRef')"></el-input-number>
      </el-form-item>
      <el-form-item prop="number" ref="maxRef">
        最大值<el-input-number v-model="dataForm.max" @blur="onBlur('minRef')" @change="onChange('minRef')"></el-input-number>
</el-form-item>
...
methods: {
    onBlur(relatedRef) {
      const ref = this.$refs[relatedRef];
      ref && ref.onFieldBlur();
    },
    onChange(relatedRef) {
      const ref = this.$refs[relatedRef];
      ref && ref.onFieldChange();
    },
},

输入框在blur和change的时候我们调用 onBlur 方法,里面我们调用 onFieldBlur 来手动让关联的formItem以blur方式来触发校验。

具体的原因我们可以在el-form-item的源码里面的找到

onFieldBlur() {
        this.validate('blur');
      },
      onFieldChange() {
        if (this.validateDisabled) {
          this.validateDisabled = false;
          return;
        }

        this.validate('change');
      },

更多el-form-item的源码分析可以看我之前的文章 element-ui表单源码解析之el-form-item

现在我们就实现了最大、小值的校验提示同步显示和消失了。

a-form-model-item

同理的ant design vue版的antdv也是这样类似的 需要注意的是

Form.Item 会对唯一子元素进行劫持,并监听 blur 和 change 事件,来达到自动校验的目的,所以请确保表单域没有其它元素包裹。如果有多个子元素,将只会监听第一个子元素的变化。

如果要监听的表单域不满足自动监听的条件,可以通过如下方式关联表单域:

<a-form-model-item prop="form.name" ref="name" :autoLink="false">
  <a-input v-model="other" />
  <span>hahha</span>
  <div>
    <a-input
      v-model="form.name"
      @blur="() => {$refs.name.onFieldBlur()}"
      @change="() => {$refs.name.onFieldChange()}"
    />
  </div>
</a-form-model-item>

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK