How to Validate Forms in Vue – A Step-By-Step Tutorial for Beginners
Tags: vue, beginners, validation
Published: 2024-02-11 19:00:36

## If you've ever worked with form validation in Vue, you know that it can quickly become messy and overwhelming. This is especially the case if you're just starting out with Vue3.
 
In this tutorial, I will show you how to Validate Forms in Vue composition API with SFC that allow you to build maintainable and clean forms. They'll easily be able to scale as your application grows.

Here's the demo of how it's gonna look like in the end:
[Demo](https://stackblitz.com/edit/vitejs-vite-fjbkrt?file=src%2FApp.vue)

## Here's the step by step guide we'll follow to learn validation in vue:
1. Create a Vue component with basic form and input.
2. Apply required validation on that Input.
3. Show Error for that input.
4. Add some more fields.
5. Customize error message.

## 1. Create a Vue component with basic form and input.
Let's create a basic vue component with a form that will contain only single input text field for now, we'll label and id this input field as first name. Remember ID is main part. 
```vue
<template>
  <form>
    <label for="first_name">First Name</label>
    <input id="first_name" v-model="first_name">
  </form>
</template>
<script setup>
  import {reactive} from 'vue';
  const data= reactive({ first_name:'' });
</script>
```
Now Let's learn the vue part here:
- First thing I love about vue sfc is the the script part feels like pure js. we just have to write setup.
- Second thing, In vue we declares reactive variables or most variable with 'ref' or 'reactive', so that when they change, vue can change the html or template or VDOM. If you are a beginner try to use only reactive on object type. Learn more about it from [here](https://vuejs.org/guide/essentials/reactivity-fundamentals.html).
- Thirdly, v-model which change your variable when the input value changes and vice-versa, means when you change variable via js, it updates the text in input field. You might wanna read more about it [here](https://vuejs.org/guide/components/v-model.html) .

## 2. Apply required validation on that Input.
Now we will apply validation on this input field when the form is submitted. For now we will apply only basic validation that is required, means the input should have some value. For validation we will use package `vue-nice-validate` to simplify things. We will import useVueNiceValidate function which will return vValidate directive and validateForm function.
```vue
<template>
  <form @submit.prevent="onSubmit">
    <label for="first_name">First Name</label>
    <input id="first_name" v-model="first_name" 
v-validate="'required'">
  </form>
</template>
<script setup>
  import {reactive} from 'vue';
  import { useVueNiceValidate } from 'vue-nice-validate';
  const { vValidate, validateForm } = useVueNiceValidate();

  const data= reactive({ first_name:'' });
  function onSubmit(){
    let is_form_valid = await validateForm(data); 
    if(!is_form_valid){
      //form is invalid
      return false;
    }
    //form is valid
    //call api
  }
</script>
```
- Here we want to perform some action on form submission, In js that is done via event listener similarly in vue we use [Event](https://vuejs.org/guide/essentials/event-handling) as well.
In above code `@submit.prevent` is event which call the function `onSubmit`.
- Inside `onSubmit` function we perform validation on data object with help of `validateForm` function, which return boolean value depends on data is valid or not.
- Now you might ask on what parameters did this performed the validation? for that we have declared our rules in template area inside input tag with v-validate.
- You see that vValidate thing we had imported that is called [directive](https://vuejs.org/guide/reusability/custom-directives) and can be used inside template.
- VueNiceValidate use it for reading rules w.r.t ID and data, the id that you mentioned in input, it must match with variable path you want to validate.
- If you are confused with directive you can also write rules in [object format](https://github.com/yogeshgalav/vue-nice-validate?tab=readme-ov-file#use-as-object). 
- **That's it based on your rules inside `v-validate`, `validateForm` will test `first_name` and return boolean result in promise.**

## 3. Show Error for that input.
Now off course you want to let user know, which field has error and what error, For that we must show them error. VueNiceValidate automatically generates error message for all failed fields, Which are available in formErrors returned from useVueNiceValidate().
formErrors is reactive array which has your input ids as key and error message as value. In most cases you need only first error message therefore it returns only single msg per field. If you want all use `validationFields` object. Refer [here](https://vue-nice-validate.netlify.app/guide/syntax.html)
```vue
<template>
  ...
    <input id="first_name" v-model="first_name" 
v-validate="'required'">
    <span class="text-danger">{{ formErrors['first_name'] }}</span>
  ...
</template>
<script setup>
  import {reactive} from 'vue';
  import { useVueNiceValidate } from 'vue-nice-validate';
  const { vValidate, validateForm, formErrors } = useVueNiceValidate();
...
</script>
```

## 4. Add some more fields.
this part is simple let's just create whole registration form with first_name, last_name, email, password and confirm_password. As we are adding these field to template or html, we must also store there values in variables inside same data object.
We will also add some extra rules like `email` for correct email syntax, `min:8` for minimum 8 characters and `confirmed:password` for checking if confirm_password field is same as password.
```vue
<template>
...
<input id="first_name" v-model="first_name" 
v-validate="'required'">
    <span class="text-danger">{{ formErrors['first_name'] }}</span>
...
<input id="last_name" v-model="last_name" 
v-validate="'required'">
    <span class="text-danger">{{ formErrors['last_name'] }}</span>
...
<input id="email" v-model="email" 
v-validate="'required|email'">
    <span class="text-danger">{{ formErrors['email'] }}</span>
...
<input id="password" v-model="password" 
v-validate="'required|min:8'">
    <span class="text-danger">{{ formErrors['password'] }}</span>
...
<input id="confirm_password" v-model="confirm_password" 
v-validate="'required|confirmed:password'">
    <span class="text-danger">{{ formErrors['confirm_password'] }}</span>
...
</template>
<script setup>
...
let data = reactive({
	'first_name': '',
	'last_name': '',
	'email': '',
	'password': '',
	'confirm_password': '',
});
...
</script>
``` 
All the other validation code will remain same as we are already validating data object.

## 5. Customize error message.
Now onto our last part, for your application you want to internationalise validation msgs, or doesn't like orignal message so want to show your own personalized message. VueNiceValidate let's you do that with ease as well you just have to use the following syntax in main entry file. 
I'm assuming you are using i18n for internationalization, you can use your custom formatter as well.
Just use ValidatePlugin and pass messageFormatter function as a parameter
```js
import {ValidatePlugin} from 'vue-nice-validate';
...
const messageFormatter = (rule, params)=>{
	return i18n.global.t(rule.toUpperCase(), params)
};
app.use(ValidatePlugin,{messageFormatter});
...
```
The above `messageFormatter` function will convert our rule to uppercase 'required' to 'REQUIRED', then it will find this key 'REQUIRED' in your i18n key value pairs. For more info refer [here](https://vue-nice-validate.netlify.app/guide/error-messages.html)

You can also hire me, if you have liked my knowledge, or refer me if you want to appreciate my efforts.

Thanks and Regards,
Yogesh Galav