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.
Update :
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.
2
Answers
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 thevalidate()
method and chain its response to extract thevalid
param which tells the validation status.I used script
setup
in the demo. Here is the possible solution-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:this.$refs.myForm.validate()
will always be true, sincevalidate()
returns a promise, andBoolean(new Promise())
is truethis.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):