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 ?
-
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
3 Answers
Reset to default 5In 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, sincevalidate()
returns a promise, andBoolean(new Promise())
is true this.valid
will be updated through thev-model
aftervalidate()
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条)