javascripttypescriptvuejs3vuetify.jsvuetifyjs3

Form validate() method is not working with Vue 3 and Vuetify 3


Problem Statement : I just migrated my Vue 2 application (Contains Vuetify 2) into Vue 3 (with Vuetify 3). After migrating, validate() method on form is not working as expected. It always return truthy value if still there are errors in the form fields.

(this.$refs.myForm as any & { validate: () => boolean }).validate()

OR

(this.$refs.myForm as any).validate()

Above line of code always returns promise (Assuming a truthy value).

Here is the link of Vuetify playground (Vue: 3.3.4 and Vuetify: 3.3.7)

What I tried so far ?

I tried to find the root cause of the issue and come up with the conclusion that this.$refs.myForm.validate() returns a promise (I think compiler assumes that as a truthy value).

I think I can achieve this by adding the v-model attribute in the form element and then on submit, I can check the form v-model value. Is this approach correct ? Or I have to change something in the original approach to make it work ?

Here is the playground link as per this approach.

If I am using both the solutions together, It is working as per the expectation (Showing validation errors and preventing the submit if form has any error).

Template :

<v-form ref="myForm" v-model="valid">

Script :

On submit button @click event

if ((this.$refs.myForm as any & { validate: () => boolean }).validate() && this.valid) {
  ...
}

Above solution works fine but Still thinking about best approach. If I will use validate using VForm v-model, It is only preventing the submit if there is any errors but not highlighting the errors.

Update :

I implemented the solution suggested by Neha and it is working fine as per the requirement. The only thing which I noticed is that If I am assigning validation rules on a button click event method, validation not trigger for the first field on first click but working fine on another click. Here is the Vuetify playground of the issue.

To get rid from this issue, I am using nextTick utitlity of vue and now it is validating all the fields at first click itself. Here is the working playground. Any input/suggestion on this ?


Solution

  • In Vuetify 3, the validate method returns the promise which can get resolved either using await or chaining the response using .then(). An example in documentation also demonstrates that see here.

    So, one approach for this problem could be using a ref variable on the form and on submit, simply call the validate() method and chain its response to extract the valid param which tells the validation status.

    I used script setup in the demo. Here is the possible solution-

    <template>
      <v-form ref="myForm">
        <v-container>
          <v-row>
            <v-col cols="12" md="4">
              <v-text-field
                v-model="firstname"
                :rules="nameRules"
                :counter="10"
                label="First name"
                required
              ></v-text-field>
            </v-col>
          </v-row>
          <v-btn type="submit" color="primary" @click="submitForm">Submit</v-btn>
        </v-container>
      </v-form>
    </template>
    
    <script setup lang="ts">
      import { ref } from 'vue'
      const myForm = ref();
      const firstname = ref(null);
      const nameRules = [
        value => {
          if (value) return true
          return 'Name is required.'
        },
        value => {
          if (value?.length <= 10) return true
          return 'Name must be less than 10 characters.'
        },
      ]
      const submitForm = () => {
        myForm.value?.validate().then(({valid: isValid}) => {
          console.log(isValid);
        })
      }
    </script>
    

    Here is the working demo.

    Hope this helps.