Vue.js + Vuelidate - Form Validation Example

Vue.js + Vuelidate - Form Validation Example

Vue.js + Vuelidate - Form Validation Example .Thankfully, there are great validation plugins for Vue like Vuelidate. In this article, we’ll be looking at how Vuelidate can be used to simplify

Thanks to Vue's reactivity model, it's really easy to roll your own form validations. This can be done with a simple method call on the form submit, or a computed property evaluating input data on each change.

Using your form validation can quickly become cumbersome and annoying, however, especially when the number of inputs in the form increase, or the form structure gets more complicated e.g. multi-step forms.

Thankfully, there are great validation plugins for Vue like Vuelidate. In this article, we'll be looking at how Vuelidate can be used to simplify:

  • Validation
  • Multi-step form validation
  • Child component validation
  • Error messages

We'll also see how the Vuelidate-error-extractor plugin can be used to simplify error message display per input, or as an error summary above or below the form.

Basic validation with Vuelidate

Vuelidate is data-model oriented, meaning validation rules are added to a validations object in the component definition, rather than being added directly to input elements in the DOM.

The structure must resemble that of the form object, but the number of validation rules can be dynamic and change depending on which fields need validation.

export default {
  name: "FormComponent",

  data() {
    return {
      form: {
        name: "",
        email: ""
      }
    };
  },

  validations: {
    form: {
      name: { required },
      email: { required, email }
    }
  }
  ...
};

Here's a live example:

Defining custom validators

Out of the box validation rules in Vuetify will work for most cases, but every so often you'll need a custom validator.

With Vuelidate, each validation rule is a function that returns a Boolean or Promise resolving to a Boolean. This means you can predefine your own validators in a validators.js file and just import each validator when needed.

Custom validators receive the currently validated data as a first param, and the whole data context as a second. For example, if you have a form data object and you are validating the email property, the first param will be the email itself and the second will be the whole data object.

// validators.js
export function isNameJoe(value) {
  if (!value) return true;
  return value === "Joe";
}

export function notGmail(value = "") {
  return !value.includes("gmail");
}

export function isEmailAvailable(value) {
  if (value === "") return true;

  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(value.length > 10);
    }, 500);
  });
}

// formComponent.vue
import { required, email } from "vuelidate/lib/validators";
import { isNameJoe, notGmail, isEmailAvailable } from "@/validators";

export default {
  name: "FormComponent",

  data() {
    return {
      form: {
        name: "",
        email: ""
      }
    };
  },

  validations: {
    form: {
      name: { required, isJoe: isNameJoe },
      email: { required, email, notGmail, isEmailAvailable }
    }
  },

  methods: {
    submit() {
      this.$v.form.$touch();
      // if its still pending or an error is returned do not submit
      if (this.$v.form.$pending || this.$v.form.$error) return;
      // to form submit after this
      alert("Form submitted");
    }
  }
};

You can also create custom validators with the help of a few special helpers that come packed with Vuelidate. Check out the Custom Validators section in the Vuelidate docs for examples.

Dynamically changing rules

Being able to change the validation rules on the fly can be a godsend with multi-step forms. Each step has its own rules that validate certain parts of the form data.

Vuelidate can use computed properties as validation rules. That means that you can return different rules for each step of a multi-step form.

In the example below, validations is now a function returning an object, rather just an object. This means it will be called after the component is initialized and computed properties are run.

export default {
  ... 
  data() {
    return {
      step: 1,
      maxSteps: 2,
      form: {
        name: "",
        email: ""
      }
    };
  },

  computed: {
    rules () {
      return this.step === 1 
        ? { name: { required } } 
        : { email: { required, email } }
    }
  },

  validations() {
    return {
      form: this.rules
    }
  }
}

New Vue.js Course Announced!

Looking to build fully-tested, production-ready Vue applications that are suitable for commercial purposes?

Join the pre-sale of our upcoming Enterprise Vue course!

[Learn More](/courses/enterprise-vue?utm_source=vjd-blog&utm_medium=article&utm_campaign=fhv) [See our other courses](https://courses.vuejsdevelopers.com?utm_source=vjd-blog&utm_medium=article&utm_campaign=fhv)
Breaking down large forms into child components

Once a form gets bigger, you might want split up your form into several smaller components to avoid having a mega component handling all the form validation.

However, storing form data in separate components rather than in a single place makes collecting the data harder. You could loop each child component via a ref binding and get the data, either implementing a data fetcher method or naming the form data in a specific way.

Another way is to store form data in Vuex, where you define all the rules on the parent and create a computed property referencing the store’s form state. Pass down the validator to each component if needed.

Tip: if using Vuex for form data, try the vuex-map-fields plugin to reduce boilerplate by setting each field as a computed property.

For most cases, I keep all the data and validation rules on a parent wrapping component that passes down the relevant validator to each child as a prop and handles sending the data to the server.

Each smaller component then uses the $touch() method on its validator prop to note that data is being changed and emits changed data via $emit('input', value) for easy v-model binding.

To make the validator available to all children, you have a few options:

  • Pass it down as a prop to each component
  • Use the Provide/Inject API
  • Create a new Vue instance in the store itself. Check this gist on how that might work

Here's a live example of the first method i.e. passing the down as a prop to each component. This is the simplest to comprehend and in most situations will be the one you will want to use.

Once we've covered error message display, I'll show you an example using the Provide/Inject API.

Validation error display

So the form is in place, its validated on each key press, but what about displaying error messages to the users?

We can just check each validator for errors and color our inputs, but what if we wanted to show a message? What if there is a need to display more than one error at a time? If/else checks start flying around everywhere.

<div class="form-group" :class="{ 'hasError': v.$error }">
  <label class="mr-2 font-bold text-grey">Email</label>
  <input type="email" class="input" v-model="email" placeholder="[email protected]" @input="v.$touch()">
  <div class="text-sm mt-2 text-red" v-if="v.$error">
    <div v-if="!v.required">Email is required</div>
    <div v-if="!v.notGmail">Email should not be a Gmail one</div>
    <div v-if="!v.isEmailAvailable">Email is not available (less than 10 char)</div>
    <div v-if="!v.email">Email is not a properly formatted email address</div>
  </div>
</div>

As you can see there is a lot of repetition there, a lot of checking, you need to know what validators each field has. Adding a new rule means you have to go and edit the template too.

Error display with Vuelidate-error-extractor

There is a better way! Vuelidate-error-extractor, which I wrote, does the heavy lifting for you by extracting all the errors for each field, finding the appropriate error message for each rule and displaying it. It gives the user a flexible way of displaying errors with minimal boilerplate and repetitiveness.

You can use one of the built-in templates for Bootstrap and Foundation or just as easily build our own to suit your needs. All you need to do is register the plugin, define an object containing common error messages and register the template you want to use. We will refer to the single input error display as singleErrorExtractor

Creating custom error display components

Vuelidate-error-extractor loops the validations for each form data and checks each rule if it's valid or not. The invalid ones are then extracted and a validation error message is assigned to them.

The bundled singleErrorExtractorMixin provides a set of helper methods and computed properties to assist the developer with building their own input error display.

<template>
  <div class="form-group" :class="{ hasError: hasErrors, hasSuccess: isValid }">
    <div class="label">
      {{ label }}
    </div>
    <div class="control"><slot/></div>
    <div class="control-helper text-red mt-4 text-sm" v-if="hasErrors">
      <div v-for="error in activeErrorMessages" :key="error">{{ error }}</div>
    </div>
  </div>  
</template>
<script>
import { singleErrorExtractorMixin } from "vuelidate-error-extractor";

export default {
  mixins: [singleErrorExtractorMixin]
};
</script>

Now just wrap your input with the new component:

<form @submit.prevent="handleForm">
  <form-group :validator="v" label="Email">
    <input
      class="input"
      type="email"
      v-model="email"
      placeholder="[email protected]"
      @input="v.$touch()"
    >
  </form-group>
</form>

Check out custom templates docs for a detailed explanation on how to make your own error display.

Being so flexible means that you can adapt it to any Vue UI framework you wish. Here is a list of popular UI frameworks and examples how to implement it for each one: https://dobromir-hristov.github.io/vuelidate-error-extractor/other_frameworks.html

Form error summary

Sometimes you need to have a summary of all the errors in a form, be it on top or at the bottom.

You can use the prebuilt components for Foundation or Bootstrap, use the baseMultiErrorExtractor component or the multiErrorExtractor mixin. For 90% of use cases, the baseMultiErrorExtractor will suffice.

<template>
  <base-errors v-bind="$attrs">
    <div class="text-red" slot-scope="{ errorMessage }">{{ errorMessage }}</div>
  </base-errors>
</template>
<script>
import { templates } from "vuelidate-error-extractor";
export default {
  inheritAttrs: false,
  components: {
    baseErrors: templates.multiErrorExtractor.baseMultiErrorExtractor
  }
};
</script>

It will reuse the same error messages that you defined up front for the singleErrorExtractor to use. The $validator must be passed as a prop.

To be able to assign a proper field label to each error, it requires an object called attributes to be defined where the error messages were defined. This object represents a map annotating how each field should be called, i.e. { name: "Name", email: "Email" }.

Reducing boilerplate by injecting the validator

Passing the validator and attribute prop to each form input and the multiErrorExtractor can get annoying quite fast, not to mention the boilerplate.

To overcome this, you can use the provided form-wrapper component to inject the validator down to all inputs.

<template>
  <div class="form pt-6">
    <form-wrapper :validator="$v.form">
      <form-summary/>
      <form @submit.prevent="submit" novalidate>
        <div class="flex text-center my-6 text-left">
          <div class="w-1/2">
            <name-component v-model="form.name"/>
          </div>
          <div class="w-1/2">
            <email-component v-model="form.email"/>
          </div>
        </div>
        <div class="text-center">
          <button type="submit" class="button">
            Submit
          </button>
        </div>
      </form>
    </form-wrapper>
  </div>
</template>

This method uses the Provide/Inject API to pass down the $validator to all the components that need it. Each form-group can then drop its validator and attribute props, to be replaced by a single name prop, annotating which field in the form it represents.

It will also try to figure out the input's attribute property by checking the attributes object we defined earlier.

Summary

Handling and validating forms on the front end as you saw, can often become a pain in the bum, especially when forms become big and need to be split up.

Using Vuelidate makes the whole ordeal a lot more bearable. In tandem with Vuelidate-error-extractor, displaying error messages under each input can go from a tedious repetitive chore, to simply adding a wrapping component or two, that do it all for you.

Code examples

Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

What’s new in HTML6

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

JavaScript Tutorial: if-else Statement in JavaScript

JavaScript Tutorial: if-else Statement in JavaScript

This JavaScript tutorial is a step by step guide on JavaScript If Else Statements. Learn how to use If Else in javascript and also JavaScript If Else Statements. if-else Statement in JavaScript. JavaScript's conditional statements: if; if-else; nested-if; if-else-if. These statements allow you to control the flow of your program's execution based upon conditions known only during run time.

Decision Making in programming is similar to decision making in real life. In programming also we face some situations where we want a certain block of code to be executed when some condition is fulfilled.
A programming language uses control statements to control the flow of execution of the program based on certain conditions. These are used to cause the flow of execution to advance and branch based on changes to the state of a program.

JavaScript’s conditional statements:

  • if
  • if-else
  • nested-if
  • if-else-if

These statements allow you to control the flow of your program’s execution based upon conditions known only during run time.

  • if: if statement is the most simple decision making statement. It is used to decide whether a certain statement or block of statements will be executed or not i.e if a certain condition is true then a block of statement is executed otherwise not.
    Syntax:
if(condition) 
{
   // Statements to execute if
   // condition is true
}

Here, condition after evaluation will be either true or false. if statement accepts boolean values – if the value is true then it will execute the block of statements under it.
If we do not provide the curly braces ‘{‘ and ‘}’ after if( condition ) then by default if statement will consider the immediate one statement to be inside its block. For example,

if(condition)
   statement1;
   statement2;

// Here if the condition is true, if block 
// will consider only statement1 to be inside 
// its block.

Flow chart:

Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate If statement 

var i = 10; 

if (i > 15) 
document.write("10 is less than 15"); 

// This statement will be executed 
// as if considers one statement by default 
document.write("I am Not in if"); 

< /script> 

Output:

I am Not in if
  • if-else: The if statement alone tells us that if a condition is true it will execute a block of statements and if the condition is false it won’t. But what if we want to do something else if the condition is false. Here comes the else statement. We can use the else statement with if statement to execute a block of code when the condition is false.
    Syntax:
if (condition)
{
    // Executes this block if
    // condition is true
}
else
{
    // Executes this block if
    // condition is false
}


Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate If-else statement 

var i = 10; 

if (i < 15) 
document.write("10 is less than 15"); 
else
document.write("I am Not in if"); 

< /script> 

Output:

i is smaller than 15
  • nested-if A nested if is an if statement that is the target of another if or else. Nested if statements means an if statement inside an if statement. Yes, JavaScript allows us to nest if statements within if statements. i.e, we can place an if statement inside another if statement.
    Syntax:
if (condition1) 
{
   // Executes when condition1 is true
   if (condition2) 
   {
      // Executes when condition2 is true
   }
}

Example:

<script type = "text/javaScript"> 

// JavaScript program to illustrate nested-if statement 

var i = 10; 

if (i == 10) { 

// First if statement 
if (i < 15) 
	document.write("i is smaller than 15"); 

// Nested - if statement 
// Will only be executed if statement above 
// it is true 
if (i < 12) 
	document.write("i is smaller than 12 too"); 
else
	document.write("i is greater than 15"); 
} 
< /script> 

Output:

i is smaller than 15
i is smaller than 12 too
  • if-else-if ladder Here, a user can decide among multiple options.The if statements are executed from the top down. As soon as one of the conditions controlling the if is true, the statement associated with that if is executed, and the rest of the ladder is bypassed. If none of the conditions is true, then the final else statement will be executed.
if (condition)
    statement;
else if (condition)
    statement;
.
.
else
    statement;


Example:

<script type = "text/javaScript"> 
// JavaScript program to illustrate nested-if statement 

var i = 20; 

if (i == 10) 
document.wrte("i is 10"); 
else if (i == 15) 
document.wrte("i is 15"); 
else if (i == 20) 
document.wrte("i is 20"); 
else
document.wrte("i is not present"); 
< /script> 

Output:

i is 20

How to Retrieve full Profile of LinkedIn User using Javascript

How to Retrieve full Profile of LinkedIn User using Javascript

I am trying to retrieve the full profile (especially job history and educational qualifications) of a linkedin user via the Javascript (Fetch LinkedIn Data Using JavaScript)

Here we are fetching LinkedIn data like Username, Email and other fields using JavaScript SDK.

Here we have 2 workarounds.

  1. Configuration of linkedIn developer api
  2. Javascript Code to fetch records

Configuration of linkedIn developer api

In order to fetch records, first we need to create developer api in linkedin which will act as token/identity while fetching data from other linkedin accounts.

So to create api, navigate to https://linkedin.com/developer/apps and click on 'Create Application'.

After navigating, fill in details like name, description and other required fields and then submit.

As we submit, it will create Client ID and Client Secret shown below, which we will be using in our code while communicating to fetch records from other LinkedIn account.

Note: We need to provide localhost Url here under Oauth 2.0. I am using my localhost, but you can probably use other production URLs under Oauth 2.0 where your app is configured. It will make your api  consider the Url as trusted which fetching records.

Javascript Code to fetch records

For getting user details like first name, last name,User image can be written as,

<script type="text/javascript" src="https://platform.linkedin.com/in.js">  
    api_key: XXXXXXX //Client ID  
    onLoad: OnLinkedInFrameworkLoad //Method that will be called on page load  
    authorize: true  
</script>  
<script type="text/javascript">  
    function OnLinkedInFrameworkLoad() {  
        IN.Event.on(IN, "auth", OnLinkedInAuth);  
    }  
  
    function OnLinkedInAuth() {  
        IN.API.Profile("me").result(ShowProfileData);  
    }  
  
    function ShowProfileData(profiles) {  
        var member = profiles.values[0];  
        var id = member.id;  
        var firstName = member.firstName;  
        var lastName = member.lastName;  
        var photo = member.pictureUrl;  
        var headline = member.headline;  
        //use information captured above  
        var stringToBind = "<p>First Name: " + firstName + " <p/><p> Last Name: " + lastName + "<p/><p>User ID: " + id + " and Head Line Provided: " + headline + "<p/>"  
        document.getElementById('profiles').innerHTML = stringToBind;  
    }  
</script>    

Kindly note we need to include 'https://platform.linkedin.com/in.js' as src under script type as it will act on this Javascript SDK provided by Linkedin.

In the same way we can also fetch records of any organization with the companyid as keyword.

<head>  
    <script type="text/javascript" src="https://platform.linkedin.com/in.js">  
        api_key: XXXXXXX ////Client ID  
        onLoad: onLinkedInLoad  
        authorize: true  
    </script>  
</head>  
  
<body>  
    <div id="displayUpdates"></div>  
    <script type="text/javascript">  
        function onLinkedInLoad() {  
            IN.Event.on(IN, "auth", onLinkedInAuth);  
            console.log("On auth");  
        }  
  
        function onLinkedInAuth() {  
            var cpnyID = XXXXX; //the Company ID for which we want updates  
            IN.API.Raw("/companies/" + cpnyID + "/updates?event-type=status-update&start=0&count=10&format=json").result(displayCompanyUpdates);  
            console.log("After auth");  
        }  
  
        function displayCompanyUpdates(result) {  
            var div = document.getElementById("displayUpdates");  
            var el = "<ul>";  
            var resValues = result.values;  
            for (var i in resValues) {  
                var share = resValues[i].updateContent.companyStatusUpdate.share;  
                var isContent = share.content;  
                var isTitled = isContent,  
                    isLinked = isContent,  
                    isDescription = isContent,  
                    isThumbnail = isContent,  
                    isComment = isContent;  
                if (isTitled) {  
                    var title = isContent.title;  
                } else {  
                    var title = "News headline";  
                }  
                var comment = share.comment;  
                if (isLinked) {  
                    var link = isContent.shortenedUrl;  
                } else {  
                    var link = "#";  
                }  
                if (isDescription) {  
                    var description = isContent.description;  
                } else {  
                    var description = "No description";  
                }  
                /* 
                if (isThumbnailz) { 
                var thumbnailUrl = isContent.thumbnailUrl; 
                } else { 
                var thumbnailUrl = "http://placehold.it/60x60"; 
                } 
                */  
                if (share) {  
                    var content = "<a target='_blank' href=" + link + ">" + comment + "</a><br>";  
                    //el += "<li><img src='" + thumbnailUrl + "' alt=''>" + content + "</li>";  
                    el += "<li><div>" + content + "</div></li>";  
                }  
                console.log(share);  
            }  
            el += "</ul>";  
            document.getElementById("displayUpdates").innerHTML = el;  
        }  
    </script>  
</body>  

We can get multiple metadata while fetching records for any any organization. We can get company updates as shown below.

Conclusion

We can also fetch any company specific data like company job updates/post, total likes, comments, and number of views along with a lot of metadata we can fetch which I have shown below.

Thank you for reading !

Making a Game in VueJS using Vuex | VueJS Tutorial

Making a Game in VueJS using Vuex | VueJS Tutorial

Today we create a Game in VueJS using Vuex to manage our state. This is an open source community driven game and I would love for you to get involved. We explore the game loop, upgrades, levelling and much more

Today we create a Game in VueJS using Vuex to manage our state. This is an open source community driven game and I would love for you to get involved. We explore the game loop, upgrades, levelling and much more. We looking into VueJS lifecycle methods as well as Vuex mutations, getters and state.

A Javascript Project

Day 15 #31Days31Videos