JavaScriptLaravelVue js

How to validate field in Vue js

The default HTML5 validation doesn’t show all the form errors at once. The irony though is that the browser actually knows all the invalid fields once a user submits, so now all we have to do is check for them and then display however we like.

Let’s now add an id to our form and a listener that captures the submit event using Vuejs.

<form class="needs-validation" id="validated-form">
  <div class="row">
    <div class="col-md-6 mb-3">
      <label for="firstName">First name</label>
      <input type="text" class="form-control" id="firstName" placeholder="" value="" required>
      <div class="invalid-feedback">
        Valid first name is required.
      </div>
    </div>
    <div class="col-md-6 mb-3">
      <label for="lastName">Last name</label>
      <input type="text" class="form-control" id="lastName" placeholder="" value="" required>
      <div class="invalid-feedback">
        Valid last name is required.
      </div>
    </div>
  </div>
  <!-- Rest of the form removed to save space   -->
  <button class="btn btn-primary btn-lg btn-block" type="submit" @click.prevent="submitForm()">SUBMIT</button>
</form>

Then in our form-validation.js file, we will initialize Vuejs and create methods to handle the form submission and validation.

const vueApp = new Vue({
    el: '#validated-form',
    methods: {
        submitForm () {
            if (this.validateForm()) {
                console.log('formValidated');
                //submit form to backend
            }
        },
        validateForm () {
            var formId = 'validated-form';
            var nodes = document.querySelectorAll(`#${formId} :invalid`);
            console.log(nodes);
            return true;
        }
    }
});

Here we created 2 methods submitForm and validate the form. submitForm calls validate form which should return true if all the validation rules are met. For now, we just console log all the invalid form inputs. If we then inspect each one we can find a number of interesting properties including the validation message which we can display to our users.

Next, let’s create the data properties that will hold the validation errors for each of the invalid inputs. Then we will loop through the array of invalid inputs to set each one.

const vueApp = new Vue({
    el: '#validated-form',
    data: function () {
        return {
            validationErrors: {
                firstName: null,
                lastName: null,
                username: null,
                email: null,
                address: null,
                country: null,
                state: null,
                zip: null,
            }
        }
    },
    methods: {
        submitForm () {
            if (this.validateForm()) {
                alert('Form Submitted')
                //submit form to backend
            }
        },
        validateForm () {
            var formId = 'validated-form';
            var nodes = document.querySelectorAll(`#${formId} :invalid`);
            var errorObjectName = 'validationErrors';
            var vm = this; //current vue instance;

            Object.keys(this[errorObjectName]).forEach(key => {
                this[errorObjectName][key] = null
            });

            if (nodes.length > 0) {
                nodes.forEach(node => {
                    this[errorObjectName][node.name] = node.validationMessage;
                    node.addEventListener('change', function (e) {
                        vm.validateForm();
                    });
                });

                return false;
            }
            else {
                return true;
            }
        }
    }
});

Here we have done a number of things. We created the validation error data property to hold the error messages for each field. Each property of the validation error object corresponds to the name attribute of each form element being validated. So in the validate form method, we clear out any previous error messages and then loop through the invalid fields to set their corresponding validation errors. We also added an event listener that re-validates once the invalid field has changed.

Now we need to add name attributes to each field we want to validate, which is quite normal when making forms. Then, of course, we should also add the span elements that will display our error messages to the user.

<form class="needs-validation" id="validated-form">
    <div class="row">
        <div class="col-md-6 mb-3">
            <label for="firstName">First name</label>
            <input type="text" class="form-control" name="firstName" placeholder="" value="" required>
            <span class="text-danger" v-if="validationErrors.firstName" v-text="validationErrors.firstName"></span>
        </div>
        <div class="col-md-6 mb-3">
            <label for="lastName">Last name</label>
            <input type="text" class="form-control" name="lastName" placeholder="" value="" required>
            <span class="text-danger" v-if="validationErrors.lastName" v-text="validationErrors.lastName"></span>
        </div>
    </div>

    <div class="mb-3">
        <label for="username">Username</label>
        <div class="input-group">
            <div class="input-group-prepend">
                <span class="input-group-text">@</span>
            </div>
            <input type="text" class="form-control" name="username" placeholder="Username" required>
            <span class="text-danger" v-if="validationErrors.username" style="width: 100%;" v-text="validationErrors.username"></span>
        </div>
    </div>

    <div class="mb-3">
        <label for="email">Email <span class="text-muted">(Optional)</span></label>
        <input type="email" class="form-control" name="email" placeholder="you@example.com">
        <div class="text-danger" v-if="validationErrors.email" style="width: 100%;">
            <span v-text="validationErrors.email"></span>
        </div>
    </div>
    
    <!--  Rest of form hidden for space    -->

    <button class="btn btn-primary btn-lg btn-block" type="submit"
        @click.prevent="submitForm()">SUBMIT</button>
</form>

Now once we submit the form our users can see all the validation errors they need to fix. What’s cool is that we have done it without having to bring in an extra library just for validation. Now because we’re leveraging Vue’s data binding powers we can really get creative from here on how we want our errors to be displayed.

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button