Vuejs Form Example

Vuejs Form Example

Let’s see how to work with html forms when using Vue by way of a vuejs form example. This tutorial will cover several topics and will also include a live demonstration you can try for yourself. In forms, there are many input types to deal with and we will cover most of them here. We’ll see how to fetch values from input fields and how to work with that data. In addition, we’ll see how to work with form controls such as an email field, password field, select field, check boxes, radio buttons, as well as a custom form control we can build as a dedicated Vue component.


Text Input Binding With v-model

We can start with a basic text input field, where we accept a user’s email address. This is pretty easy, we’ve seen this many times. We have an <input> tag which has the vue specific markup highlighted.

<div class="form-group">
    <label for="email">Your Email Address</label>
    <input type="text"
           id="email"
           class="form-control"
           v-model="userData.email">
</div>

In the <script> section we set up the data() method to associated the data with the UI. The data() method returns an object as we know, but we are also setting up a nested userData object to hold the email property. This is because we will be adding more properties in the form and the userData object works like a nice namespace.

<script>
    export default {
        data() {
            return {
                userData: {
                    email: ''
                }
            }
        }
    }
</script>

Password Input Binding and v-model.lazy

Now we can add a text input which binds to a password. This example will work almost exactly like the snippet above. There is one difference however. We are adding the .lazy modifier to the v-model. What this does is to sync the input data to the data object *after* a change event such as moving focus to a different field. This might be handy in a form when you don’t want to apply any validation until a user hits the submit button and everything is fully filled out.

<div class="form-group">
    <label for="password">Enter Password</label>
    <input type="password"
           id="password"
           class="form-control"
           v-model.lazy="userData.password">
</div>

We can add this new password property to the userData object in our data() method.

<script>
    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                }
            }
        }
    }
</script>

Number Typecast with v-model.number

This form is a type of review form and the user is able to include a numeric review from 1 to 10. For this type of data binding, we can make use of v-model.lazy. This is helpful because even when you use type=”number” in the form, the value of HTML input elements always returns a string.

<div class="form-group">
    <label for="satisfaction">Satisfaction (10 for best, 1 for worst)</label>
    <input min="1"
           max="10"
           type="number"
           id="satisfaction"
           class="form-control"
           v-model.number="userData.satisfaction">
</div>

We will need to add this data property as well in our <script>.

<script>
    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                    satisfaction: '',
                }
            }
        }
    }
</script>

Working With Textarea

Now we can add a text area to the form as well where a user can add a few sentences as part of their review. Note that you need to use v-model to bind data to the text area. If you try to use interpolation between <textarea> and </textarea> it will not work.

<div class="form-group">
    <label for="message">Your Message</label>
    <textarea id="message"
              rows="5"
              class="form-control"
              v-model="message"></textarea>
</div>

Let’s also add the message property to our data() area.

<script>
    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                    satisfaction: '',
                },
                message: 'Describe your review...'
            }
        }
    }
</script>

Checkboxes Use an Array

Now we will move on to using checkboxes which are a little different because you can have multiple true values in collection of checkboxes in a form. Here are two checkboxes which are part of the same form. This means a user could select both at the same time if they like. Note that both inputs have the same v-model=”checkboxOptions” binding. In the case of the user wanting the daily special as well as the monthly coupons they would be checking both checkboxes.


<div class="form-group">
    <label for="sendspecial">
        <input type="checkbox"
               id="sendspecial"
               value="sendSpecial"
               v-model="checkboxOptions"> I Want Today's Special
    </label>
    <br>
    <label for="sendCoupons">
        <input type="checkbox"
               id="sendcoupons"
               value="sendCoupons"
               v-model="checkboxOptions"> Send Me Monthly Coupons
    </label>
</div>

We handle this in the script area by making use of a simple array like we see here.

<script>
    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                    satisfaction: '',
                },
                message: 'Describe your review...',
                checkboxOptions: []
            }
        }
    }
</script>

Radio Buttons are Single Value

Radio buttons look similar to checkboxes but the difference is that a collection of radio buttons only allows one option to be selected. We want to know if our user is male or female, we we can add this markup here. Both inputs share the same v-model=”radioBoxOption” binding, but only one will be used in the data().

<label for="male">
    <input type="radio"
           id="male"
           value="Male"
           v-model="radioBoxOption"> Male
</label>
<label for="female">
    <input type="radio"
           id="female"
           value="Female"
           v-model="radioBoxOption"> Female
</label>

Since the radioBoxOption property only supports one value, we can set it up as such and pre populate the value with ‘Male’.

<script>
    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                    satisfaction: '',
                },
                message: 'Describe your review...',
                checkboxOptions: [],
                radioBoxOption: 'Male'
            }
        }
    }
</script>

Select Inputs

The form can include a select dropdown menu to allow a user to choose the priority level of this review. Since a <select> input has many nested <option> tags, we can make use of v-for to render all of them.


<label for="priority">Priority</label>
<select id="priority"
        class="form-control"
        v-model="selectedPriority">
    <option v-for="priority in priorities">{{ priority }}</option>
</select>

In the data() area, we will need to properties for this. One for priorities and one for selectedPriority. Note that priorities is an array of values, and this is how the v-for in the template is able to render out many <option> values.

<script>
    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                    satisfaction: '',
                },
                message: 'Describe your review...',
                checkboxOptions: [],
                radioBoxOption: 'Male',
                selectedPriority: 'High',
                priorities: ['High', 'Medium', 'Low']
            }
        }
    }
</script>

v-model for Custom Controls

You can add a custom control to a form by building one as a separate component if you like. Let’s build a component where a user can select true or false, similar to how two radio buttons might work. We can create this component in a separate file of Switch.vue.

Switch.vue

<template>
    <div>
        <div id="on"
             @click="switched(true)"
             :class="{active: value}">On
        </div>
        <div id="off"
             @click="switched(false)"
             :class="{active: !value}">Off
        </div>
    </div>
</template>

<script>
    export default {
        props: ['value'],
        methods: {
            switched(isOn) {
                this.$emit('input', isOn);
            }
        }
    }
</script>

<style scoped>
    #on, #off {
        width: 45px;
        height: 25px;
        background-color: lightgray;
        padding: 4px;
        display: inline-block;
        margin: 11px -3px;
        box-sizing: content-box;
        cursor: pointer;
        text-align: center;
    }

    #on:hover, #on.active {
        background-color: #77ee79;
    }

    #off:hover, #off.active {
        background-color: #f08e8d;
    }
</style>

Now we need to import this in App.vue and register it as a component.

<script>
    import Switch from './Switch.vue';

    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                    satisfaction: 10
                },
                message: 'Describe your review...',
                checkboxOptions: [],
                radioBoxOption: 'Male',
                selectedPriority: 'High',
                priorities: ['High', 'Medium', 'Low'],
                customSwitch: true,
            }
        },
        components: {
            customSwitch: Switch
        }
    }
</script>

With this now set up, we can actually render this switch in our form like this.

<custom-switch v-model="customSwitch"></custom-switch>

Submit and Prevent

So what are we going to do with this form data? Well for our purposes, we are just going to add a way to display the data entered to the user. By default, the form is going to try and submit to a server, but we don’t really want to do that. To prevent that from happening, we can simply use the .prevent modifier as seen here.

<button class="btn btn-primary"
        @click.prevent="submitted">Submit!
</button>

Here is the final markup for the <script> area. The button is actually triggering a submitted() method now. All that method does is to set the value of the isSubmitted property to true.

<script>
    import Switch from './Switch.vue';

    export default {
        data() {
            return {
                userData: {
                    email: '',
                    password: '',
                    satisfaction: 10
                },
                message: 'Describe your review...',
                checkboxOptions: [],
                radioBoxOption: 'Male',
                selectedPriority: 'High',
                priorities: ['High', 'Medium', 'Low'],
                customSwitch: true,
                isSubmitted: false
            }
        },
        methods: {
            submitted() {
                this.isSubmitted = true;
            }
        },
        components: {
            customSwitch: Switch
        }
    }
</script>

We’ll use this isSubmitted data property to decide whether or not to show the data to the user by way of a v-if.

<div class="card" v-if="isSubmitted">
    <div class="card-body">
        <h4 class="card-title">Form Data</h4>

        <p>Mail: <b>{{ userData.email }}</b></p>
        <p>Password: <b>{{ userData.password }}</b></p>
        <p>Satisfaction: <b>{{ userData.satisfaction }}</b></p>
        <p style="white-space: pre">Message: <b>{{ message }}</b></p>
        <p>Checkbox Options:</p>
        <ul>
            <li v-for="item in checkboxOptions"><b>{{ item }}</b></li>
        </ul>
        <p>Gender: <b>{{ radioBoxOption }}</b></p>
        <p>Priority: <b>{{ selectedPriority }}</b></p>
        <p>Switched: <b>{{ customSwitch }}</b></p>
    </div>
</div>

Try it out!

Go ahead and take the form we built for a test drive.


Vuejs Form Example Summary

We learned a good deal about forms and VueJs in this tutorial. We covered how to use all of the standard html form controls in addition to creating our very own custom control as a Vue component. During the course of this, we saw how to use v-model for our data binding, and some special cases where we might need to make use of a modifier such as lazy or number. Finally, we provided a nice demo where you can test out the data bindings on your own.