Search code examples
validationvuejs3vuetify.js

Why my vuetify form validator is not checking if fields are valid?


Before i go to the problem, it is worth mentioning - i am running Vue3 and Vuetify 3.

The problem is with the this.$refs.form.validate() function, where the passed in check doesn't check if the form is valid or not. This is making me very anxious at this stage.

My form is pretty much simple:

<template>
    <v-form ref="patientDetailsForm" @submit.prevent>
        <v-row>
            <v-col
                cols="12"
                md="2"
            >
                <v-select
                    :items="nameTitles"
                    v-model="formFields.title"
                    label="Title"
                    :rules="[requiredValidator]"
                />
            </v-col>
            <v-col
                cols="12"
                md="4"
            >
                <v-text-field
                    v-model="formFields.first_name"
                    label="First Name"
                    placeholder="First Name"
                    :rules="[requiredValidator]"
                />
            </v-col>
            // there are similar fields, not included here
        </v-row>
        // there are similar fields, not included here
        <v-row>
            <v-col cols="8">
                <v-btn
                    @click="submitForm"
                    variant="elevated"
                    color="primary"
                    block
                >
                    Create A New Patient
                </v-btn>
            </v-col>
            // Other action buttons not relevant
        </v-row>
    </v-form>
</template>

And here is my <script> which is very very basic as you can see:

<script lang="ts">
import {defineComponent} from "vue";
import { emailValidator, requiredValidator } from '@validators'

export default defineComponent({
    data() {
        return {
            nameTitles: [
                'Mr.',
                'Mrs.',
            ],
            formFields: {
                first_name: null,
                title: null,
                // Other fields commented..
            },
        }
    },
    emits: ['sendNewPatientForm'],
    methods: {
        emailValidator,
        requiredValidator,
        submitForm() {
            this.$refs.patientDetailsForm.validate((valid: boolean) => {
                console.log('[FORM] Form validation result:', valid);
                // This is where the problem is! I can't get to "valid" var
                if (valid) {
                    console.log('[FORM] submitForm');
                    this.$emit('sendNewPatientForm', this.formFields);
                }
            });
        },
    },
});
</script>

The problem is with the line this.$refs.patientDetailsForm.validate((valid: boolean) => {. The valid is not passing anything, and i can't access the valid part, no logs are returned.

My @validators are just various const export ... constants wrapped in one .ts file. That is not the problem.

I have tried to wrap it in this.$nextTick(). But that didn't solve the issue. Next i have tried to create an empty rules: {} object and reference it before this.$nextTick() so this.$refs.form.validate() would have fresh rules to check against - nothing, same quetness from this.$refs.form.validate().

Also i have printed a log to console, where this.$refs.patientDetailsForm.validate() is indeed working and printing the results (first invalid form, then valid form):

a console log output


Solution

  • VForm's validate() does not accept any arguments, passing a callback does nothing. Instead, it returns a promise that you can await:

    methods: {
      async submitForm() {
        const {valid, errors} = await this.$refs.patientDetailsForm.validate()
        if (valid) {
         ...
    

    Consider using VForm's @submit event, it works with programmatic submits too, and it receives the promise as input argument, so you can do without the template ref:

    <v-form @submit.prevent="submitForm">
    

    and

    methods: {
      async submitForm(submitEventPromise) {
        const {valid, errors} = await submitEventPromise
        if (valid) {
         ...