javascript - Form validate() method is not working with Vue 3 and Vuetify 3 - Stack Overflow

Problem Statement : I just migrated my Vue 2 application (Contains Vuetify 2) into Vue 3 (with Vuetify

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 e up with the conclusion that this.$refs.myForm.validate() returns a promise (I think piler 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 ?

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 e up with the conclusion that this.$refs.myForm.validate() returns a promise (I think piler 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 ?

Share Improve this question edited Aug 10, 2023 at 12:22 Rohìt Jíndal asked Aug 9, 2023 at 11:41 Rohìt JíndalRohìt Jíndal 27.2k15 gold badges77 silver badges132 bronze badges 4
  • it's due to vuetify 3's new design to move closer to Material UI to support Promise rules I remend using await instead of trying to catch synchronous events or you may prefer @submit.prevent – Tachibana Shin Commented Aug 9, 2023 at 12:37
  • Maybe this is helpful – Moritz Ringler Commented Aug 9, 2023 at 13:12
  • I am using nextTick() and inside that performing this validation. – Rohìt Jíndal Commented Aug 9, 2023 at 15:30
  • @MoritzRingler I added the update in the question. Can you please have a look and provide your input ? – Rohìt Jíndal Commented Aug 9, 2023 at 15:38
Add a ment  | 

3 Answers 3

Reset to default 5

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.

Hmm, I am pretty sure your solution does not work the first time, as the @click handler on the submit button will run before the submit event is triggered on the VForm or any other global validation could finish. So that means on the first click, when you do:

if ((this.$refs.myForm as any & { validate: () => boolean }).validate() && this.valid) {
  ...
}
  • the this.$refs.myForm.validate() will always be true, since validate() returns a promise, and Boolean(new Promise()) is true
  • this.valid will be updated through the v-model after validate() has finished or when validation on every input has been triggered manually (this is how it is implemented)

On subsequent clicks, validate() will have run at least once, so :modelValue will reflect the current validation status. So at that point, it works.

Using nextTick as you suggest will make execution wait, but for a more or less unrelated event. Waiting for the promise from validation() is the more direct and reliable approach and makes more sense semantically, so I would suggest to use that.


So I think the best solution is the one suggested by Vuetify, where you await the promise passed to the @submit handler (which is also more robust than using @click on the submit button, as it covers programmatic submits too):

async function submit(submitEventPromise: SubmitEventPromise) {
  const {valid, errors} = await submitEventPromise
  if (valid) {
    ...

(SubmitEventPromise is the typescript type, it is exported by Vuetify)

A simple way to fix this is :

<template>
<v-form 
   ref="form_tecnico"
   v-model="valid"
   lazy-validation>
     <v-select class="mt-0"
          item-title="usu_nombre"
          item-value="usu_id"
          v-model="selectTecnico"
          :items="rsListaTecnico"
          label="Técnicos"
          return-object
          variant="underlined"
          :rules="nRules"
          hint="Seleccione el técnico"
          persistent-hint>
      </v-select>
</v-form>
</template>

<script setup lang="ts">
  import { ref } from 'vue'
  const form_tecnico = ref<any>(null);
  const isValid = await form_tecnico.value?.validate()

  if(isValid.valid) 
  { 
    //All the logic you need after validation 
  }
</script>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1743933993a4532321.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信