3
votes

Code Sandbox with exact example

https://codesandbox.io/s/veevalidate-components-vuetify-iftco

In the example above, when I enter a wrong value in the input field, the Validation state returns Valid == true, but it should return false.

I understand that this happens because the @input event method (resize) will run first and then it will assign the value to :value. In other words, vee-validate checks the existing value before the event is fired.

Not sure how to fix it so that the input value is first validated and then the method is run!

How to replicate problem:

  1. Open the console
  2. Change the value of the width field to 5
  3. You will successfully get an error message under the field but the Valid flag in the console is set to true, even though the field is not valid after the method is done.

I am not sure how to fix this. I have been trying for hours..

<template>
  <v-app>
    <v-row>
      <v-col v-for="(value, key) in fixture.dimensions" :key="key">
        <ValidationProvider
          :rules="`between:${fixture.limits[key].min},${fixture.limits[key].max}`"
          v-slot="{ errors, valid }"
        >
          <v-text-field
            :value="fixture.dimensions[key]"
            @input="resize(key, valid)"
            :label="key"
            ref="key"
            :min="fixture.limits[key].min"
            :max="fixture.limits[key].max"
            :error-messages="errors"
            outlined
            type="number"
          ></v-text-field>
        </ValidationProvider>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
import { ValidationProvider } from "vee-validate";

export default {
  name: "App",
  components: {
    ValidationProvider
  },
  data: () => ({
    fixture: {
      dimensions: {
        width: 1000,
        height: 1500
      },
      limits: {
        width: {
          min: 300,
          max: 1500
        },
        height: {
          min: 300,
          max: 1500
        }
      }
    }
  }),
  mounted() {
    console.log(this.fixture);
  },
  methods: {
    resize(key, valid) {
      console.log("valid?", valid);
      this.fixture.dimensions[key] = event.target.value;
      // this.fixture.iconObject.resize()
    }
  }
};
</script>
1

1 Answers

0
votes

If you are not using v-model to manage the input, you should explicitly call validate yourself, like this:

   <ValidationProvider
      :rules="`between:${fixture.limits[key].min},${fixture.limits[key].max}`"
      v-slot="{ errors, valid, validate }"
    >
      <v-text-field
        :value="fixture.dimensions[key]"
        @input="resize(key, $event, validate)"
        ...
      ></v-text-field>
    </ValidationProvider>

resize(key, value, validate) {
  validate(value).then(result => {
    console.log("valid???");
    console.log(result.valid);

    //either way update value
    this.fixture.dimensions[key] = value;
  });
}

In the callback from validate, you get a result object that includes whether the result is valid, and also which rules failed (in result.failedRules) and any error messages in an array (in result.errors). See it working here: https://codesandbox.io/s/veevalidate-components-vuetify-ynll5