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
Here's the step by step guide we'll follow to learn validation in vue:
- Create a Vue component with basic form and input.
- Apply required validation on that Input.
- Show Error for that input.
- Add some more fields.
- 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.
<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.
- 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 .
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.
<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 as well.
In above code
@submit.prevent
is event which call the functiononSubmit
. - Inside
onSubmit
function we perform validation on data object with help ofvalidateForm
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 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.
- That's it based on your rules inside
v-validate
,validateForm
will testfirst_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
<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.
<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
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
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
Top comments (0)