Powerful and meaningful validation in Vue — Using Indicative

Karthick Ramachandran
4 min readJan 3, 2020

--

If you’re writing your validation logic or using vuelidate but looking for a better alternative, This post is what you have to read.

This is what we’re going to build

Creating a new Vue app using Vue CLI

We’ll start by creating a new Vue app using Vue CLI. I’ll name it as vueindcative.

vue create vueindicativecd vueindicativenpm run serve or yarn serve

Say hello to indicative 👋

We’re going to use a library called indicative which was built by the AdonisJs team.

Quick note: I created a default Vue app. No routes, stores.

Let’s do some cleanup

Your App.vue should look like this

<template><div id="app"><HelloWorld /></div></template><script>import HelloWorld from "./components/HelloWorld.vue";export default {name: "app",components: {HelloWorld}};</script><style>#app {font-family: "Avenir", Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;}</style>

New Vue app comes with HelloWorld.vue component, We’ll make use of it.

In HelloWorld.vue, Copy and paste this HTML.

<template><div><div>placeholder="enter your password"/></div><button>Login</button></div></template>

Writing our State and two-way bindings with V-model

Our data() is very simple. We have to define email, password and errors. Forgive me for bad code formatting (I have to do it manually here)

<script>
export default {
data() {return {email: "",password: "",errors: []};}}
</script>

After defining the states, we’ll connect it with the v-model in the template. Now your input tags will look like

<input v-model="email" placeholder="enter your email" type="email" /><inputtype="password"v-model="password"placeholder="enter your password"/>

Great!.

Now two-way bindings should work. Whenever we type something in the input, It should update the data belongs to that input.

Wait, We’ll add a click listener to the button

<button @click="submit">Login</button>

Sure enough, we need to write a method to handle submit an event. After closing the data(), You should paste this

methods: {submit() {}
}

Now when you click the button submit method will be triggered.

Time to work with Indicative

Install indicative

yarn add indicative or npm install indicative

That’s it, we don’t need any additional setup.

Writing our first validation

There is a method called validate that comes with the indicative validator. It will look like this. You can make use of this and do validation in any JavaScript you want.

import { validate } from "indicative/validator";

Import it in your HelloWorld.vue component.

validate() is a function that mostly accepts three arguments. It is important to pass at least two.

We’ll pass data we need to validate and the rules for validation as of now.

SO now your submit method will look like

methods: {submit() {const rules = {email: "required|email",password: "required|min:4"};const data = { email: this.email, password: this.password };
validate(data, rules)
.then(data => {this.errors = [];alert("Everything is good");}).catch(err => (this.errors = err));}}

The above code is simple.

We’re writing the rules as an object (which is the convention) which comes with a lot of helpers we can use. Just setting email will do a valid email check. min is for the minimum and max for the maximum etc. Find more helpers here.

The data object is what we want to validate. In our case email and password.

So finally validate(data, rules) which means valid my data and these are my rules.

Validate returns a promise so .then will return success response. Catch all the errors with .catch where your valuable validation messages will go. So we’re setting these messages in our error state.

See

.catch(err => (this.errors = err));

Now you can get all the error messages from the error array. Indicative validator sets error messages on its own.

You can pull out the message from the error object returned by indicative. Console log for what are the things it returns.

Show it in HTML like this

<div class="error" v-for="error in errors" :key="error.message"><h4>{{ error.message }}</h4></div>

Add some styles to error class to make it look better

<style scoped>.error {display: inline-block;width: 300px;background-color: red;color: white;}</style>

Wait, I can’t see where I can change the default error messages that come with indicative. Yes, If you remember I said we can pass three arguments to validate() function right.

Now, We’ll write a message object.

const messages = {"email.required": "Email is required","email.email": "Email should be valid","password.min": "Password should have at least 4 characters","password.required": "Password is required"};

Now our validate will be data in want to validate, the rules and I don’t want the default message so this is my custom error message.

validate(data, rules, messages)

That’s it.

Quick note: validate() will stop if one of the fields validation fails. To prevent this, You have to use validateAll()

S0 instead of validate(), It should be validateAll().

Our final HelloWorld.vue will look like

<template><div><div class="error" v-for="error in errors" :key="error.message"><h4>{{ error.message }}</h4></div><div><input v-model="email" placeholder="enter your email" type="email" /></div><div><inputtype="password"v-model="password"placeholder="enter your password"/></div><button @click="submit">Login</button></div></template><script>import { validate } from "indicative/validator";export default {data() {return {email: "",password: "",errors: []};},methods: {submit() {const rules = {email: "required|email",password: "required|min:4"};const messages = {"email.required": "Email is required","email.email": "Email should be valid","password.min": "Password should have at least 4 characters","password.required": "Password is required"};const data = { email: this.email, password: this.password };validate(data, rules, messages).then(data => {this.errors = [];alert("Everything is good");}).catch(err => (this.errors = err));}}};</script>
<style scoped>
.error {display: inline-block;width: 300px;background-color: red;color: white;}</style>

A happy new year and happy coding.

Follow me on twitter

--

--