11

I'm creating a form using Vuetify's v-form in Vue using their Composition API and <script setup>. Using v-form's rules, I've created a way to validate user input; however, once the form is submitted, I need to clear the form's fields. When the fields are reset (using empty strings), the form rules are triggered and validation errors appear. I would like to access v-form's built-in functions (e.g., clear()); however, I can't access this.$refs.form in <script setup>. How can I access these functions or just clear my form without triggering validation rule errors after submission?

Here is the script portion so far:

<script setup lang="ts">
import { ref, Ref } from 'vue'
import { Service } from '@/types/service'

const service: Ref<Service> = ref({ name: '', endpoint: '' })
const loading = ref(false)
const isValid = ref(true)

const register = () => {
  loading.value = true
  isValid.value = false
  clear()
  setTimeout(() => {
    loading.value = false
  }, 2000)
}

const clear = () => {
  service.value = { name: '', endpoint: '' }
}

const serviceNameRules = [
  (v: string) => !!v || 'Service name is required',
  (v: string) =>
    v.length <= 20 || 'Service name must be less than 20 characters',
]

const endpointRules = [
  (v: string) => v.length <= 100 || 'Endpoint must be less than 100 characters',
  (v: string) =>
    isURL(v) ||
    'Endpoint must have a valid URL format (i.e., "http://example.com")',
]

const isURL = (str: string) => {
  try {
    const url = new URL(str)
    return url.protocol === 'http:' || url.protocol === 'https:'
  } catch (_) {
    return false
  }
}
</script>

Here is my template form

<template>
  <v-card elevation="5">
    <v-progress-linear
      v-if="loading"
      class="position-absolute"
      style="z-index: 1"
      color="#0062B8"
      height="10"
      indeterminate
    />

    <v-card-title>Register New Service</v-card-title>
    <v-card-text>
      <v-form
        @submit.prevent="register()"
        v-model="isValid"
        ref="form"
        lazy-validation
      >
        <v-text-field
          v-model="service.name"
          label="Service Name"
          hint="e.g., 'service-pages'"
          :rules="serviceNameRules"
          required
        />
        <v-text-field
          v-model="service.endpoint"
          label="Endpoint"
          hint="https://www.example.com/page"
          :rules="endpointRules"
          required
        />
        <v-btn
          type="submit"
          color="#0062B8"
          style="color: white"
          :disabled="!isValid"
        >
          Register
        </v-btn>
      </v-form>
    </v-card-text>
  </v-card>
</template>

2 Answers 2

7

Try to create a form ref inside your script which is automatically bound to ref="form":

<script setup lang="ts">
import { ref, Ref } from 'vue'
import { Service } from '@/types/service'

const service: Ref<Service> = ref({ name: '', endpoint: '' })
const loading = ref(false)
const isValid = ref(true)

const form=ref<HTMLFormElement>(null)

....
 // then use it like 
 if(form.value){
     form.value.reset()
  }
 //or
  form.value?.reset()
....

Sign up to request clarification or add additional context in comments.

4 Comments

I've tried this but I encounter the TypeScript error that Property 'clear' does not exist on type 'never'.ts(2339)
Try out const form=ref<any>(null) or const form=ref<HTMLFormElement>(null)
Great! I was able to use const form = ref<HTMLFormElement>() and, when using the correct function name (i.e., reset()) like this form.value?.reset(), I got my expected result! Thanks for the direction!
Also, I was able to be more specific in my typings by importing import { VForm } from 'vuetify/lib/components/index' and using const form = ref<typeof VForm>()
2

Since the question is specifically about getting a reference to a Vuetify VForm component, the correct approach is:

<template>
   <v-form ref="myForm">
       <!-- ... -->
   </v-form>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { VForm } from 'vuetify/components';

const myForm = ref<InstanceType<typeof VForm> | null>(null);

const myMethod = () => {
    // now you can call methods from the Vuetify API on the instance, e.g.
    myForm.value?.resetValidation();
};
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.