Building a Form in Vue using Tailwind CSS and VeeValidate (Part 2)
Maxwell Adapoe
Posted on May 25, 2021
This is part 2 of 2 on how to create a simple login form with validation using Vue.js, Tailwind CSS and VeeValidate for validation.
You can clone the example app from my repo on Github.
Link to Part 1 here
Part 2: Creating our form and adding validation
In this Part we will look at creating our form and hooking up Veevalidate for frontend form validation
Creating the form
Create a new vue component Login.vue
in your src/views
folder. You can use the command below
touch src/views/Login.vue
paste the below code into the file:
<template>
<div class="flex justify-center items-center mt-52">
<div class="w-full max-w-xs">
<form class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
<div class="identity-input mb-4">
<label
for="identity"
class="block text-gray-700 text-sm font-bold mb-2"
>
Email</label
>
<input
id="identity"
class="shadow appearance-none borderrounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
type="text"
placeholder="Email"
aria-describedby="emailHelp"
v-model="email"
/>
<span class="text-xs text-red-700" id="emailHelp"></span>
</div>
<div class="password-input mb-6">
<label
for="identity"
class="block text-gray-700 text-sm font-bold mb-2"
>Password</label
>
<input
aria-describedby="passwordHelp"
v-model="password"
class="shadow appearance-none borderrounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
id="password"
type="password"
placeholder="*******"
/>
<span class="text-xs text-red-700" id="passwordHelp"></span>
</div>
<div class="flex items-center justify-between">
<button
class="bg-blue-600 hover:bg-black text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
type="submit"
>
Sign In
</button>
<a
class="inline-block align-baseline font-bold text-sm text-blue-500 hover:text-blue-800"
href="#"
>
Forgot Password?
</a>
</div>
</form>
</div>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
email: "",
password: "",
};
},
methods: {
login() {
console.log("logging in");
},
},
};
</script>
Setting up the Login Route
in your routes/index.js
file add the below
...
import Login from '../views/Login.vue'
...
const routes = [
...,
{
path: '/login',
name: 'Login',
component: Login
},
]
...
in your App.vue file add
...
<router-link
to="/link"
class="block ml-4 mt-4
lg:inline-block lg:mt-0 text-blue-200
hover:text-white"
>Login</router-link>
...
With this in place navigating to http://localhost:8080/#/login
should look like this :
Setting up VeeValidate
To add validation we need to install VeeValidate
npm install vee-validate --save
Once installation is complete in your main.js
add
javascript
...
import {extend,ValidationObserver, ValidationProvider} from 'vee-validate';
import * as rules from 'vee-validate/dist/rules';
Vue.component('ValidationObserver', ValidationObserver);
Vue.component('ValidationProvider', ValidationProvider);
Object.keys(rules).forEach(rule => {
extend(rule, rules[rule]);
});
...
extend
Allows you to add more rules to be used globally by the vee-validate functions and components.
ValidationObserver
is a component that wraps your forms and provides aggregated validation state for all the fields nested under it.
ValidationProvider
component is a component that wraps your inputs and provides validation states.
We then import all the the default rules using import * as rules from 'vee-validate/dist/rules';
and iterate over them using the Object.keys(rules).forEach
function.
With that in place we can move on to making the magic Happen.
Adding Validation to the form.
We now need to wrap our form component with the ValidationObserver component
...
<ValidationObserver ref="loginForm">
<form >
...
</form>
</ValidationObserver>
...
The Validation Provider now goes around our inputs. It accepts a v-slot="v"
attribute. To make things a little less verbose we can use ES6's object destructing and replace it with v-slot="{ errors }"
.
It also accepts a name attribute which is used in displaying the error messages and also accepts the validation rules.
Read more about registering the Validation Provider heere
With this in place we can now make use of the errors and display them in our html as well
<ValidationProvider name="Email" rules="required|email" v-slot="{ errors }">
<div class="email-input mb-4">
<label
for="email"
class="block text-gray-700 text-sm font-bold mb-2"
>
Email</label
>
<input
id="email"
class="shadow appearance-none borderrounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
type="text"
placeholder="Email"
aria-describedby="emailHelp"
v-model="email"
/>
<span class="text-xs text-red-700" id="emailHelp">{{
errors[0]
}}</span>
</div>
</ValidationProvider>
<ValidationProvider
name="Password"
rules="required|min:6"
v-slot="{ errors }"
>
<div class="password-input mb-6">
<label
for="password"
class="block text-gray-700 text-sm font-bold mb-2"
>Password</label
>
<input
aria-describedby="passwordHelp"
v-model="password"
class="shadow appearance-none borderrounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
id="password"
type="password"
placeholder="*******"
/>
<span class="text-xs text-red-700" id="emailHelp">{{
errors[0]
}}</span>
<span class="text-xs text-red-700" id="passwordHelp"></span>
</div>
</ValidationProvider>
Finally we need to ensure that the Validation Observer is triggered when the submit button is pressed to ensure that validation has been passed successfully.
We need to add a v-slot="{ handleSubmit }"
to our Validation Observer and also add an @submit.prevent
event listener to our form
...
<ValidationObserver v-slot="{ handleSubmit }" ref="loginForm">
<form @submit.prevent="handleSubmit(login)" class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
...
That sums it up. Your page should look like this once you click the submit button without entering any values or when you enter an invalid value for your email / password
Posted on May 25, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.