Vue show and hide form elements

David CarrDavid Carr
4 min read

Introduction

When working with forms, it is common to display or conceal various fields based on the options selected.

I'll use Vue to conditionally show or hide form elements.

In this example, I'm going to use an SFC (Single File Component) for ease of us. You'll see this in full in the putting it all together section below.

For this to work it does not need to use a SFC, the HTML and JS will work when used in traditional setups i.e. having JS in javascript blocks and the HTML in a page's body.

Creating the form elements

Here I have 2 select elements, imagine the insurance type should only be displayed if the answer to Do you want insurance? was Yes

<div>
  <label for="insurance">Do you want insurance?</label>
  <select id="insurance">
    <option value="">Select</option>
    <option>Yes</option>
    <option>No</option>
  </select>
</div>

<div>
  <label for="insuranceType">Insurance Type</label>
  <select id="insuranceType">
    <option value="">Select</option>
    <option>Home</option>
    <option>Travel</option>
  </select>
</div>

Binding Form Elements

First, we need to create variables to bind the elements. Inside a script tag define a const for each element.

<script setup>
import {ref} from "vue";

const insurance = ref();
const insuranceType = ref();
</script>

Notice that ref is imported from Vue, as by default, no directives are available for variables.

ref() allows the variable to be reactive, meaning that Vue will monitor it and re-render the action whenever its state changes.

To bind the elements with the variables use v-model this creates a 2-way binding.

<div>
  <label for="insurance">Do you want insurance?</label>
  <select id="insurance" v-model="insurance">
    <option value="">Select</option>
    <option>Yes</option>
    <option>No</option>
  </select>
</div>

<div>
  <label for="insuranceType">Insurance Type</label>
  <select id="insuranceType" v-model="insuranceType">
    <option value="">Select</option>
    <option>Home</option>
    <option>Travel</option>
  </select>
</div>

Show / Hide elements select

Now to only show the insurance type when the question Do you want insurance? is set to Yes

This can be accomplished by wrapping the second select in a div and using a v-show directive.

<div v-show="insurance === 'Yes'">

v-show takes a condition that has a truthy value, this must equate to true or false. When true the body of the div will be displayed, otherwise its not rendered to the page.

<div>
<label for="insurance">Do you want insurance?</label>
<select id="insurance" v-model="insurance">
  <option value="">Select</option>
  <option>Yes</option>
  <option>No</option>
</select>
</div>

<div v-show="insurance === 'Yes'">

  <div>
    <label for="insuranceType">Insurance Type</label>
    <select id="insuranceType" v-model="insuranceType">
      <option value="">Select</option>
      <option>Home</option>
      <option>Travel</option>
    </select>
  </div>

</div>

Taking this a step further have additional select elements that only appear when an insurance type is selected.

I have 2 divs that will only render when the insuranceType value matches either Home or Travel which matches the option selected from the Insurance Type select menu.

<div>
  <label for="insuranceType">Insurance Type</label>
  <select id="insuranceType" v-model="insuranceType">
    <option value="">Select</option>
    <option>Home</option>
    <option>Travel</option>
  </select>
</div>

<div v-show="insuranceType === 'Home'">
  <p>Home Details</p>
</div>

<div v-show="insuranceType === 'Travel'">
  <p>Travel Details</p>
</div>

Show or hide checkbox

What about when you have a checkbox that should render markup but only when it's checked, how may that work?

Let's create a input element with a type of checkbox, we'll v-model bind a variable called addAComment:

<div>
  <label for="addAComment">Add a comment?</label>
  <input id="addAComment" type="checkbox" v-model="addAComment">
</div>

Update the Javascript:

const addAComment = ref();

Now add a v-model to the checkbox

Next, create a div with a v-show this time it only needs the variable, when the checkbox is set it will have a value otherwise it will not. This is enough to activate v-show

<div>
  <label for="addAComment">Add a comment?</label>
  <input id="addAComment" type="checkbox" v-model="addAComment">
</div>

<div v-show="addAComment">

  <div>
    <label for="comment">Comment</label><br>
    <textarea id="comment" v-model="comment"></textarea><br>
    {{ comment }}
  </div>

</div>

Putting it all together

<script setup>
import {ref} from "vue";

const insurance = ref();
const insuranceType = ref();
const addAComment = ref();
const comment = ref();
</script>

<template>

  <div>
    <label for="insurance">Do you want insurance?</label>
    <select id="insurance" v-model="insurance">
      <option value="">Select</option>
      <option>Yes</option>
      <option>No</option>
    </select>
  </div>

  <div v-show="insurance === 'Yes'">

    <div>
      <label for="insuranceType">Insurance Type</label>
      <select id="insuranceType" v-model="insuranceType">
        <option value="">Select</option>
        <option>Home</option>
        <option>Travel</option>
      </select>
    </div>

    <div v-show="insuranceType === 'Home'">
      <p>Home Details</p>
    </div>

    <div v-show="insuranceType === 'Travel'">
      <p>Travel Details</p>
    </div>

  </div>

  <div>
    <label for="addAComment">Add a comment?</label>
    <input id="addAComment" type="checkbox" v-model="addAComment">
  </div>

  <div v-show="addAComment">

    <div>
      <label for="comment">Comment</label><br>
      <textarea id="comment" v-model="comment"></textarea><br>
      {{ comment }}
    </div>

  </div>

</template>

<style>
label {
  padding-right: 5px;
}
</style>

How v-show differs from v-if

It's important to note that v-show and v-if serve similar purposes in controlling element visibility, but they have some key differences:

v-show: The element is always rendered in the DOM, but its CSS display property is toggled between none and the original value (e.g., block, inline, etc.) to show or hide it. This makes it more efficient for elements that frequently toggle between visible and hidden states.

v-if: The element is conditionally created or destroyed in the DOM. When the condition is false, the element is completely removed from the DOM. This can be more efficient when you have elements that are rarely used or have complex rendering logic, as they are not in the DOM until needed.

11
Subscribe to my newsletter

Read articles from David Carr directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

David Carr
David Carr

Blogger at http://dcblog.dev.