Processing a form can be a long and tedious task when using vanilla JavaScript or jQuery. While those tools can help to make your AJAX forms very clean, and provide your user with immediate feedback and validations, writing the code can become a bit convoluted.

Processing forms with Vue however is an easy task. With data-binding and reactivity, we can quickly process a form since all the inputs are bound to the variables we have.

Let's take a look at processing a form with vanilla JavaScript and then see how easy Vue makes the job.

Table of Contents

    For this tutorial, we won't have any backend service to process the form; we'll just be alerting when the form is processed. You can hook in your own backends later.

    The Form's HTML

    To get us started, we'll be creating a simple form with two inputs:

    • Name
    • Email

    We'll also be using Bulma for some CSS stylings. You can check out this writeup on Bulma for more info: Get to Know Bulma: My Current Favorite CSS Framework

    NLl72lS8SiSKYtv714a9_get-to-know-bulma-favorite-flexbox-css-framework.png.jpg

    Here's the HTML:

    <div class="hero is-fullheight is-info is-bold">
    <div class="hero-body">
    <div class="container">
    
      <h1 class="title has-text-centered">Vue.js Form Processing</h1>
      <div class="box">
    
        <!-- our signup form ===================== -->
        <form id="signup-form">
          <!-- name -->
          <div class="field">
            <label class="label">Name</label>
            <input type="text" class="input" name="name">
          </div>
    
          <!-- email -->
          <div class="field">
            <label class="label">Email</label>
            <input type="email" class="input" name="email">
          </div>
    
          <!-- submit button -->
          <div class="field has-text-right">
            <button type="submit" class="button is-danger">Submit</button>
          </div>
        </form>
    
      </div>
    
    </div>
    </div>
    </div>

    We've got quite a bit of markup, but that's all to get some Bulma styling and spacing for our form.

    • hero classes get us this nice blue background
    • field classes get us spacing for the form
    • input and button classes style our form elements

    At this point, our form looks like this:

    Very nice!

    Submitting with JavaScript

    Let's work on submitting this form with JavaScript. Here's the steps that we'll have to take to submit the form:

    • Grab the form
    • Grab the inputs in the form
    • Listen for the form's submit event
    • Grab the values of our inputs
    • Process!

    All simple steps and easy to write but when you start writing the same code over and over for multiple forms, it becomes tedious. Let's see how we do this in vanilla JS and then see how Vue takes care of writing all the boilerplate code (grabbing elements and listening for events).

    1: Grab the Elements We Need

    // grab the things we need
    const signupForm = document.getElementById('signup-form');
    const nameInput  = signupForm.querySelector('input[name=name]');
    const emailInput = signupForm.querySelector('input[name=email]');

    We'll grab the #signup-form using it's id. Then we'll search its children for the correct inputs.

    2. Listen for the Form's Submit Event

    Next, we'll use an event listener to listen for the submit event on the form.

    // listen for the submit event
    signupForm.addEventListener('submit', processSignupForm);
    function processSignupForm(e) {
      e.preventDefault();
    
      // form processing here
    }

    Now, we are listening for the event and preventing the default behavior of the form. By using e.preventDefault(), we are stopping the form from refreshing the page which forms normally do. This would be problematic since we want to process the form with JS and AJAX and not a round trip request.

    3. Grab the Input Values

    Inside the event listener, let's grab the input values.

    // listen for the submit event
    signupForm.addEventListener('submit', processSignupForm);
    function processSignupForm(e) {
      e.preventDefault();
    
      // get our data
      const name  = nameInput.value;
      const email = emailInput.value;
    
      console.log({ name, email });
    
      // process the form!
      alert('Processing!');
    
    }

    Here we're creating new name and email values that we can use when processing our form. We would send this information to our backend. We're also using an alert() in place of an HTTP request to a backend like Node or PHP. We would normally use something like axios or fetch to create the request.

    Here's everything working nicely once we submit the form. We can see the console logging and the alert:

    Here's the CodePen for the JavaScript way:

    Problems with Vanilla JS Methods

    That's how we would process the form with JS. While this is perfectly acceptable for smaller forms, let's imagine we start to scale this form:

    • more inputs
    • select, radio, and checkboxes
    • ajax requests on selecting checkboxes
    • validation

    All those scenarios start to add up the code we will need to write. For each of the above tasks we have to do the same tasks:

    • get elements
    • listen for events
    • grab data
    • send AJAX request

    Vue allows us to hide all those boilerplate tasks since data in our Vue instance is automatically bound to our HTML.

    Vue takes care of the boilerplate code to grab elements, listen to events, and inject data.

    Let's take a look at how Vue handles this scenario.

    The Vue Way

    We'll be using the same HTML from earlier. Let's start by creating our Vue instance. We know what data we'll need for this demo: name and email.

    const app = new Vue({
      el: '#signup-form',
    
      // our data
      data: {
        name: '',
        email: ''
      }
    });

    We have our Vue instance looking at the form with the id of signup-form. This way Vue knows exactly which part of our app to work with.

    Bind Data to Form Inputs

    Next up, we need to bind these two variables to our two inputs. Update the inputs to have the v-model directive.

    ...
    
    <input 
      type="text"
      class="input" 
      name="name"
      v-model="name">
    
    ...
    
    <input 
      type="email" 
      class="input" 
      name="email" 
      v-model="email">
    ...

    We'll use v-model to bind a data variable to an input. Now whenever this input changes, it is immediately reflected in our Vue instance. We no longer have to grab the input element or its value. It's automatically bound thanks to Vue!

    You can visit your browser console and type:

    app.name = 'My New Name';

    Press enter and you'll immediately see your form input change!

    Submitting the Form

    We have our data grabbed and bound. The last thing we need to take care of is listening to the submit event and submitting the form.

    Vue lets us do this easily since it has a v-on directive where we can listen to submit like so: v-on:submit

    Updating Our Template

    We'll use the shorthand of v-on:submit: @submit. Update the opening form tag to add the directive:

    <form id="signup-form" @submit.prevent="processForm">

    We're also adding the .prevent to automatically prevent the form's default behavior (refreshing the page). We are saying "when the form is submitted, use the processForm method.

    Processing the Form

    Let's create that now. Inside our Vue instance, let's add the methods and our new processForm method:

    const app = new Vue({
      el: '#signup-form',
    
      // our data
      data: {
        name: '',
        email: ''
      },
    
      // our methods
      methods: {
        processForm: function() {
          console.log({ name: this.name, email: this.email });
          alert('Processing!');
        }
      }
    });

    To access our data variables from within methods, we can use the this. syntax. this refers to the parent Vue instance and that gives us direct access to our data variables.

    Our form is ready for processing! If we ever needed to bind new input values, we'd just need to create the inputs and add the variable to our data.

    It's also easy to add more methods and v-on directives to listen for other form events like blur, keyup, change and more.

    Conclusion

    While this was a simple example, I hope you can see the value of Vue in processing forms. Vue handles all of the boring code for grabbing, listening, and injecting. Now we can focus on the code that we want to focus on.

    Chris Sevilleja

    173 posts

    Co-founder of Scotch.io. Slapping the keyboard until something good happens.