Day 22: Conditional Form Fields
Build a form where specific fields appear or disappear based on the user's selected answers.
JavaScript focus
- reading selected form values
- using change events
- showing and hiding conditional sections
- toggling hidden
- matching selected values to field groups
Nice extras
- use radio buttons or a select menu
- use data-* attributes to connect answers to field groups
- add a visible active state to the selected option
- use hidden for inactive groups
- include one simple submit button
- keep validation light
MDN prep
Conditional Form
The HTML
<form class="conditional_form" novalidate>
<div class="form_field">
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
<p class="error_message" id="name-error" hidden>Please enter your name.</p>
</div>
<div class="form_field">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<p class="error_message" id="email-error" hidden>Please enter a valid email.</p>
</div>
<fieldset class="form_fieldset">
<legend>What are you interested in?</legend>
<label>
<input type="radio" name="inquiry_type" value="website" data-show="website-fields" required>
Website project
</label>
<label>
<input type="radio" name="inquiry_type" value="consulting" data-show="consulting-fields">
Consulting session
</label>
<label>
<input type="radio" name="inquiry_type" value="code-review" data-show="code-review-fields">
Code review
</label>
</fieldset>
<p class="error_message" id="interest-error" hidden>Please select your interest.</p>
<div class="conditional_group" id="website-fields" hidden>
<div class="form_field">
<label for="website-type">What kind of website do you need?</label>
<select id="website-type" name="website_type">
<option value="">Choose one</option>
<option value="landing-page">Landing page</option>
<option value="portfolio">Portfolio site</option>
<option value="business-site">Business site</option>
<option value="existing-site-updates">Updates to an existing site</option>
</select>
</div>
<div class="form_field">
<label for="website-timeline">What is your ideal timeline?</label>
<select id="website-timeline" name="website_timeline">
<option value="">Choose one</option>
<option value="asap">As soon as possible</option>
<option value="1-month">Within 1 month</option>
<option value="2-3-months">2-3 months</option>
<option value="flexible">Flexible</option>
</select>
</div>
</div>
<div class="conditional_group" id="consulting-fields" hidden>
<div class="form_field">
<label for="consulting-topic">What do you want help with?</label>
<select id="consulting-topic" name="consulting_topic">
<option value="">Choose one</option>
<option value="html-css">HTML/CSS</option>
<option value="javascript">JavaScript</option>
<option value="accessibility">Accessibility</option>
<option value="career">Frontend career direction</option>
</select>
</div>
<div class="form_field">
<label for="session-length">Preferred session length</label>
<select id="session-length" name="session_length">
<option value="">Choose one</option>
<option value="30">30 minutes</option>
<option value="60">60 minutes</option>
<option value="90">90 minutes</option>
</select>
</div>
</div>
<div class="conditional_group" id="code-review-fields" hidden>
<div class="form_field">
<label for="repo-url">GitHub repo or project URL</label>
<input type="url" id="repo-url" name="repo_url">
</div>
<div class="form_field">
<label for="review-focus">What should I focus on?</label>
<select id="review-focus" name="review_focus">
<option value="">Choose one</option>
<option value="html-structure">HTML structure</option>
<option value="css-layout">CSS/layout</option>
<option value="javascript">JavaScript</option>
<option value="accessibility">Accessibility</option>
</select>
</div>
</div>
<div class="form_field">
<label for="message">Anything else I should know?</label>
<textarea id="message" name="message" rows="5"></textarea>
</div>
<div class="form_buttons">
<!-- submit the form -->
<button type="submit" class="button">Send Inquiry</button>
<!-- reset the form -->
<button type="reset" class="text_button">Reset</button>
</div>
</form>
The JavaScript
function initConditionalForm() {
const root = document.querySelector(".conditional_form");
if (!root) return;
const inquiryType = root.querySelectorAll('input[name="inquiry_type"]');
const groups = root.querySelectorAll(".conditional_group");
const reset = root.querySelector(".text_button");
const name = root.querySelector('input[name="name"]');
const email = root.querySelector('input[name="email"]');
const interestError = root.querySelector("#interest-error");
const nameError = root.querySelector("#name-error");
const emailError = root.querySelector("#email-error");
/**
* logic to show groups based on radio input
*/
inquiryType.forEach((type) => {
type.addEventListener("change", (e) => {
interestError.hidden = true;
const show = type.dataset.show;
groups.forEach((group) => {
group.hidden = true;
const id = group.getAttribute("id");
if (id === show) {
group.hidden = false;
}
});
});
});
/**
* light form vaildation
*/
root.addEventListener("submit", (e) => {
// name input
if (name.value === null || name.value === "") {
e.preventDefault();
nameError.hidden = false;
return;
} else {
nameError.hidden = true;
}
// email input
if (email.value === null || email.value === "") {
e.preventDefault();
emailError.hidden = false;
return;
} else {
emailError.hidden = true;
}
// check the radio group for something checked
// there can only be one
const checked = root.querySelector('input[name="inquiry_type"]:checked');
if (!checked) {
console.log({ checked });
e.preventDefault();
interestError.hidden = false;
return;
} else {
console.log("something is checked");
interestError.hidden = true;
}
// this is not a working form
// remove if there's an endpoint
e.preventDefault();
});
/**
* reset the form and hide the errors
*/
reset.addEventListener("click", () => {
groups.forEach((group) => {
group.hidden = true;
});
interestError.hidden = true;
nameError.hidden = true;
emailError.hidden = true;
});
}
initConditionalForm();