Issue using useForm() with a Modal | Vue 3 | Vee Validate 4
Tags: vue, webdev, javascript, programming
Published: 2022-11-29 19:49:30

Ever used [vee-validate](https://vee-validate.logaretm.com/v4/)? It is a nice form validation library and now with the help of [composition API](https://vee-validate.logaretm.com/v4/guide/composition-api/validation/) got even stronger.

##  Purpose of this article
Using **useForm()** to initialize a form that exist in a **modal**, the validation will run on initialization.
Thus, your form will be invalid since your fields are not existing (modal is closed). So, when you open the modal, you will get back your errors attached in your form.

## A possible solution
If you faced this problem, you might think of using [Form Component](https://vee-validate.logaretm.com/v4/api/form) to register your form instead of useForm() (Composition API).
But this is a kinda cheap solution.
By not using composition API, you don't make use of the full potential of this library.


## So, the best solution
Is to [reset](https://vee-validate.logaretm.com/v4/guide/components/handling-forms#handling-resets) the form when the modal gets opened.

## Let's see it in action

We will create a custom input element that we aim to use throughout our application.
Notice the 'undefined' we pass in useField() instead of our validation rules. This is because we want to validate at form-level and not at field-level.

The classes used are from the tailwind library, and you can have a better look in this example [repo](https://github.com/nickap/nuxt-crud/tree/master/components)
```vue
<template>
  <div class="w-full">
    <label class="label" :for="$attrs.id">{{ label }}</label>
    <input v-model="value" class="input" v-bind="$attrs">
    <div class="mt-1 text-xs text-red-500">
      <span class="text-transparent">.</span>
      <span>
        {{ errorMessage }}
      </span>
    </div>
  </div>
</template>

<script setup>
import { toRef } from 'vue';
import { useField } from 'vee-validate';
const props = defineProps({
  name: { type: String, required: true },
  label: {
    type: String,
    required: true
  },
  // whenever we use v-model, modelValue prop passed to the child
  // https://v3-migration.vuejs.org/breaking-changes/v-model.html#_3-x-syntax
  modelValue: [String, Number]
});
// Need 'toRef' to achieve reactivity with vee-validate
const name = toRef(props, 'name');
const modelValue = toRef(props, 'modelValue');
// undefined for rules because we validate on Form-Level
const { value, errorMessage } = useField(name, undefined, {
  initialValue: modelValue
});
</script>

<style></style>
```


We will use the described input component in our modal here:
```vue
<template>
  <div v-if="open">
    <!-- Form -->
    <form class="mt-5" @submit="submitFotm">
      <div class="grid grid-cols-1 gap-4 md:grid-cols-2">
        <div class="col-span-full">
          <FormInput
            id="name"
            v-model="author.name"
            name="name"
            type="text"
            label="Name"
            placeholder="Author's Name"
          />
        </div>
      </div>
      <!-- Form buttons -->
      <div class="flex items-center justify-end space-x-3 mt-7">
        <button type="button" class="px-4 text-sm bg-gray-100 py-2.5 rounded-md" @click="closeModal()">
          Cancel
        </button>
        <button type="submit" class="btn submit" :disabled="!meta.dirty">
          {{ author._id ? "Update" : "Create" }}
        </button>
      </div>
    </form>
  </div>
</template>

<script setup>
import { useForm } from 'vee-validate';
const schema = {
  name: 'required|min:3'
};

// Get function used to handle form submission and set validation schema
const { handleSubmit, meta, resetForm } = useForm({
  validationSchema: schema
});

const onInvalidSubmit = () => {
  // Form is invalid
  // U can shake the submit button and inform the user in your way
};

const submitFotm = handleSubmit((values) => {
  // Handle submision and close the modal.
  // Also, pass onInvalidSubmit() as a  callback function.
  console.log(values);
  closeModal();
}, onInvalidSubmit);

const open = ref(false);
const openModal = () => {
  // The Form will get registerd and validated on setup function.
  // So it will be invalid before we open the modal.
  // We have to reset it here.
  resetForm();
  open.value = true;
};

const closeModal = () => {
  open.value = false;
};

// We are exposing openModal() and closeModal()
// So we can handle the visibility on the parrent component
defineExpose({
  openModal,
  closeModal
});
</script>

<style></style>

```
So, we got access to the resetForm() helper and used it to reset the form when we show the modal.

You can have a better look in this minimal nuxt [repo](https://github.com/nickap/nuxt-crud/tree/master/components).

Hope you find this info helpful.

Thanks for reading this!