一个更新时如何验证两个输入字段

时间:2019-07-16 10:13:26

标签: vue.js vuetify.js

当一个值更改时,我试图验证两个输入字段。这是必需的,因为否则这两个字段之间的验证将无法正常进行。

我创建了一个示例来重现该问题,该html代码应该可以自我解释

<div id="app">
  <v-app id="inspire">
          <v-text-field
              :value="values[0]"
              :rules="firstRules"
              @input="setFirstValue"
            ></v-text-field>

            <v-text-field
              :value="values[1]"
              :rules="secondRules"
              @input="setSecondValue"
            ></v-text-field>
  </v-app>
</div>

请注意,v-model是不可能的,因为此组件将值作为prop并通过发出更新事件将更新后的值传递回父级。

vue实例:

new Vue({
  el: '#app',
  data () {
    return {
      values: [5345, 11],
      firstRules: [true],
      secondRules: [true]
    }
  },
  created: function () {
    this.setFirstValue(this.values[0])
    this.setSecondValue(this.values[1])
  },
  computed: {
    firstValidation: function () {
      return [value => value.length < this.values[1].length || "Must have less characters than second value"]
    },
    secondValidation: function () {
      return [value => value.length > this.values[0].length || "Must have more characters than first value"]
    }
  },
  methods: {
    setFirstValue: function (newValue) {
      this.values[0] = newValue
      this.firstRules = this.validateValue(this.values[0], this.firstValidation)
      this.secondRules = this.validateValue(this.values[1], this.secondValidation)
    },
    setSecondValue: function (newValue) {
      this.values[1] = newValue
      this.secondRules = this.validateValue(this.values[1], this.secondValidation)
      this.firstRules = this.validateValue(this.values[0], this.firstValidation)
    },
    validateValue: function (value, rules) {
      for (const rule of rules) {
          const result = rule(value)

          if (typeof result === 'string') {
            return [result]
          }
      }

      return [true]
    }
  }
})

在“开始”时,规则返回有效状态,但是我想在加载组件时(创建的钩子?)验证两个字段以立即更新此状态。

我必须将验证规则应用于计算所得的属性,因为它们必须访问当前值。否则,他们将验证旧值。

每个输入事件将同时验证两个字段并更新规则状态。

我创建了一个在此处玩耍的示例

https://codepen.io/anon/pen/OeKVME?editors=1010

不幸的是出现了两个问题:

  • 没有在开始时直接验证字段
  • 将一个输入字段更改为有效状态时,规则仍将返回错误消息

当一个字段更新时,如何为两个字段设置验证?

1 个答案:

答案 0 :(得分:2)

似乎您在想太多事情。

默认情况下,仅当绑定到该输入的值更改时,才会触发vuetify输入的验证逻辑。为了触发其他输入的验证,您可以将两个输入都包装在v-form组件中,并为其提供一个ref属性。这样,您将可以访问该组件的validate方法,该方法将触发表单内任何输入的验证逻辑。

模板看起来像这样:

<v-form ref="form">
  <v-text .../>
  <v-text .../>
</v-form>

并在脚本中触发验证:

mounted() {
  this.$refs.form.validate();
}

以上内容将在安装组件时验证表单,但是每当输入值发生变化时,您还需要触发两个输入的验证。为此,您可以向values添加观察者。但是,您需要在Vue更新DOM以反映validate中的更改之后调用表单的values方法。

要执行此操作,请将呼叫包装在this.$nextTick呼叫中:

watch: {
  values() {
    this.$nextTick(() => {
      this.$refs.form.validate();
    });
  }
}

或使用async functionawait this.$nextTick

watch: {
  async values() {
    await this.$nextTick();
    this.$refs.form.validate();
  }
}

因此,当组件初始化以及每一个值改变时,验证都会触发两个输入。但是,如果您希望将验证呼叫放在一个位置而不是同时放在mounted钩子和values观察者中,则可以使观察者immediate并摆脱呼叫mounted钩子。

所以这是最后一个例子:

watch: {
  immediate: true,
  async handler() {
    await this.$nextTick();
    this.$refs.form.validate();
  }
}

因此,现在验证逻辑将在预期的时间触发,但是您的验证逻辑仍然存在一个问题。组件初始化时,会将values数据属性设置为Number类型值的数组,这些类型值没有length属性。因此,例如,如果您仅将第一个输入更改为"5",而第二个输入仍为11,则(11).lengthundefined,而"5".length < undefined为{ {1}}。

无论如何,在比较它们的长度之前,您需要更改要与字符串比较的值。像这样:

false

最后,因为您可以在表单上动态调用value => (value + '').length < (this.values[1] + '').length ,所以有机会降低组件的许多复杂性。

这是简化版:

validate
Vue.config.devtools = false;
Vue.config.productionTip = false;

new Vue({
  el: '#app',
  data() {
    return {
      values: [5345, 11]
    }
  },
  computed: {
    rules() {
      const valid = (this.values[0] + '').length < (this.values[1] + '').length;
      return {
        first: [() => valid || "Must have less characters than second value"], 
        second: [() => valid || "Must have more characters than first value"]
      };
    }
  },
  watch: {
    values: {
      immediate: true,
      async handler() {
        await this.$nextTick();
        this.$refs.form.validate();
      }
    }
  }
})