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 an 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.