Dynamic Forms

A recipe for dynamic form inputs

Sometimes you want to collect data from your site’s visitors. The go to method of doing so is the form. Perhaps the form only needs to present certain queries if another form input contains some data.

Here is a quick recipe to perform just that.

Setup

The setup of this project is up to you. If you are new to VueJs, I’d recommend the GUI install. Check out the instructions here.The scope of this project is simply at the component level. So everything in this example is in just one file. That component can be easily included in a parent component.

If the form relies on data from the parent component, you’ll want to look into look into props.

The Component

Here is the script. The notes after go over the sections.

<template>
  <div id="app">
    <!-- This Displays the form if it has not been submitted yet -->
    <form v-if="!formSubmitted">
      <div class="form-group">
        <label for="visitor-name">Name:</label>
        <input id="visitor-name" v-model="formData.name">
      </div>

      <div class="form-group">
        <label for="hasPhone">Provide Phone? </label>
        <input v-on:click="handleProvidePhoneClicked" type="checkbox">
      </div>

      <div class="form-group" v-if="hasPhone">
        <label for="visitor-phone">Phone:</label>
        <input id="visitor-phone" v-model="formData.phone">
      </div>

      <button v-on:click="handleSubmit" id="submit-button">
        Submit
      </button>

      <hr>

      <p>Name: {{ this.formData.name }}</p>
      <p>Phone: {{ this.formData.phone }}</p>
    </form>

    <!-- This displays the thank you message after form submission -->
    <div v-if="formSubmitted">
      <h2>Thank you for your submission</h2>
    </div>
  </div>
</template>

<script>


export default {
  name: 'app',
  data(){
    return{
        formSubmitted: false,
        hasPhone: false,
        formData:{
          name: '',
          phone: '',
        }
    }
  },
  methods: {

    handleSubmit: function(e) {
      e.preventDefault();
      console.log(`Name: ${this.formData.name}
Phone: ${this.formData.phone}`);
    this.formData.name = '';
    this.formData.phone = '';
    this.formSubmitted = true;
    },

    handleProvidePhoneClicked: function() {
      this.hasPhone = !this.hasPhone;
    }

  },
}
</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>

Code Review

We’ve got a default template, script, style layout to this template, There are two main subsections which are either displayed or hidden using VueJs’ conditional rendering.

 <form v-if="!formSubmitted">

The data method returns a value formSubmitted,  which we set to false. Until we later change that value to true in a later method, the form will display.

Notice the following div section

<div v-if="formSubmitted">
    <h2>Thank you for your submission</h2>
</div>

If the formSubmitted variable is instead true, we’ll display a Thank you message.

We then get to the script section, where we set the data property.

data(){
    return{
        formSubmitted: false,
        hasPhone: false,
        formData:{
          name: '',
          phone: '',
        }
    }
  },

formSubmitted is responsible for keeping track of of when the form has been submitted, and can thus alter whether the form is displaying or the thank you message is displaying.

hasPhone is initially set to false as well. A checkbox on the form toggles whether this is true or false.

formData is a JavaScript object. It’s property values are initially set to empty strings. And they will store the data entered in the form. If you’re wondering how the data is bound from the form to the data property, it’s done via two way data binding made possible by the v-model directive

<input id="visitor-name" v-model="formData.name">

We then declare two methods. The handleSubmit method, which manages the steps that take place when the submit button is clicked. First it calls the preventDefault method on the event we pass it. This prevents the page from reloading when we submit the form. What follows is a console log where we out put the data stored in the formData propery. Finally, the formData property values are reset to an empty string, and the formSubmitted property is set to true.

 handleSubmit: function(e) {
      e.preventDefault();
      console.log(`Name: ${this.formData.name}
Phone: ${this.formData.phone}`);
    this.formData.name = '';
    this.formData.phone = '';
    this.formSubmitted = true;
    },

Next, the handleProvidePhoneClicked nethod is declared. All that method does is toggle what the value of the hasPhone data property, by assigning it the opposite of it’s current value.

handleProvidePhoneClicked: function() {
      this.hasPhone = !this.hasPhone;
    }

The single file component ends with the style section. CSS is beyond the scope of this article. This example is simply the css generated by the vue-cli.

Closing

We were able to use the VueJs library to quickly prototype a dynamic form. Using checkboxes, radial selectors, or even the presence of a character in a text input, one can easily add a layer of dynamic behavior to their forms.

At this point, when we submit the form, all we are doing is logging the data to the console. At this point you’ll want to make your POST request to your back-end/server side code or API in order to work with that data and persist it in a database or store.


We are working on a second part to this article where we iterate over this form and bring the form down to a nested component. This is a common workflow, and requires utilizing props. Check back soon

Don’t forget to comment on this recipe


If you found this helpful, or just want to help us out, feel free to donate as little or as much as you’d like. Every little bit goes towards helping caffeine addicts in need.

Leave a Reply

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