Day 29: JavaScript Mini Project: Build a Form Validator, Calculator, or Dynamic UI π

Building small projects is the best way to reinforce JavaScript concepts. In this post, we will create three mini-projects:
β
Form Validation β Ensure user input is correct before submission.
β
Calculator β A simple yet functional arithmetic calculator.
β
Dynamic UI Component (FAQ Accordion) β Expand/collapse sections dynamically.
π Project 1: Form Validation
Form validation ensures that users provide the correct data before submitting a form.
πΉ What is Form Validation?
Form validation is a technique to check user input before processing it. It can be client-side (JavaScript) or server-side (backend validation).
π How It Works?
- JavaScript listens for form submission.
- It checks the input fields for correct data.
- If the input is invalid, an error message is displayed.
- If valid, the form is submitted.
π Code Implementation:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Validation</title>
<style>
* {
box-sizing: border-box;
clear: both;
}
.container {
max-width: 500px;
background: gainsboro;
box-sizing: border-box;
border-radius: 5px;
padding: 20px;
margin: 0 auto;
}
.error-message {
color: red;
font-size: 14px;
display: block;
margin-top: 5px;
}
.success-message {
color: green;
font-weight: bold;
}
input {
display: block;
margin: 10px 0;
padding: 8px;
width: 100%;
border: 1px solid #ccc;
border-radius: 5px;
}
input.error {
border-color: red;
}
button {
padding: 8px 15px;
border-radius: 5px;
border: 0px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<form id="signup-form" novalidate>
<input type="text" id="username" placeholder="Enter Username" aria-describedby="username-error">
<span id="username-error" class="error-message" aria-live="polite"></span>
<input type="email" id="email" placeholder="Enter Email" aria-describedby="email-error">
<span id="email-error" class="error-message" aria-live="polite"></span>
<button type="submit">Sign Up</button>
</form>
<p id="success-message" class="success-message"></p>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const form = document.getElementById("signup-form");
const username = document.getElementById("username");
const email = document.getElementById("email");
const usernameError = document.getElementById("username-error");
const emailError = document.getElementById("email-error");
const successMessage = document.getElementById("success-message");
const validationRules = {
username: {
required: "Username cannot be empty!",
minLength: { value: 3, message: "Username must be at least 3 characters long!" },
maxLength: { value: 15, message: "Username cannot exceed 15 characters!" }
},
email: {
required: "Email cannot be empty!",
pattern: {
value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
message: "Invalid email address!"
}
}
};
function validateInput(input, rules, errorElement) {
let value = input.value.trim();
let errorMessage = "";
if (!value) {
errorMessage = rules.required;
} else if (rules.minLength && value.length < rules.minLength.value) {
errorMessage = rules.minLength.message;
} else if (rules.maxLength && value.length > rules.maxLength.value) {
errorMessage = rules.maxLength.message;
} else if (rules.pattern && !rules.pattern.value.test(value)) {
errorMessage = rules.pattern.message;
}
if (errorMessage) {
showError(input, errorMessage, errorElement);
return false;
} else {
clearError(input, errorElement);
return true;
}
}
function showError(input, message, errorElement) {
errorElement.textContent = message;
input.classList.add("error");
}
function clearError(input, errorElement) {
errorElement.textContent = "";
input.classList.remove("error");
}
username.addEventListener("input", () => validateInput(username, validationRules.username, usernameError));
email.addEventListener("input", () => validateInput(email, validationRules.email, emailError));
form.addEventListener("submit", (event) => {
event.preventDefault();
let isUsernameValid = validateInput(username, validationRules.username, usernameError);
let isEmailValid = validateInput(email, validationRules.email, emailError);
if (isUsernameValid && isEmailValid) {
successMessage.textContent = "Form submitted successfully!";
form.reset();
} else {
successMessage.textContent = "";
}
});
});
</script>
</body>
</html>
πΉ Best Practice: Use trim()
to remove unnecessary spaces and regular expressions (RegEx) for accurate email validation.
π Project 2: Calculator
A simple calculator that performs basic arithmetic operations.
πΉ What is a JavaScript Calculator?
A JavaScript calculator allows users to enter numbers and perform arithmetic operations dynamically.
π How It Works?
- Users input numbers and operators.
- JavaScript listens for button clicks.
- The entered expression is evaluated and displayed.
π Code Implementation:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculator</title>
<style>
.calculator {
width: 300px;
margin: auto;
text-align: center;
border: 2px solid #ccc;
padding: 20px;
border-radius: 10px;
background: #f9f9f9;
}
#display {
width: 100%;
font-size: 20px;
text-align: right;
margin-bottom: 10px;
padding: 10px;
box-sizing: border-box;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 5px;
}
button {
padding: 10px;
font-size: 18px;
border: none;
background: #ddd;
cursor: pointer;
}
button:hover {
background: #bbb;
}
</style>
</head>
<body>
<div class="calculator">
<input type="text" id="display" readonly>
<div class="buttons">
<button onclick="clearDisplay()">C</button>
<button onclick="appendValue('7')">7</button>
<button onclick="appendValue('8')">8</button>
<button onclick="appendValue('9')">9</button>
<button onclick="appendValue('+')">+</button>
<button onclick="appendValue('4')">4</button>
<button onclick="appendValue('5')">5</button>
<button onclick="appendValue('6')">6</button>
<button onclick="appendValue('-')">-</button>
<button onclick="appendValue('1')">1</button>
<button onclick="appendValue('2')">2</button>
<button onclick="appendValue('3')">3</button>
<button onclick="appendValue('*')">*</button>
<button onclick="appendValue('0')">0</button>
<button onclick="appendValue('.')">.</button>
<button onclick="calculateResult()">=</button>
<button onclick="appendValue('/')">/</button>
</div>
</div>
<script>
let display = document.getElementById("display");
let calculated = false; // Track if the result is already calculated
function appendValue(value) {
if (calculated) {
display.value = ""; // Reset display if new input is given after calculation
calculated = false;
}
display.value += value;
}
function calculateResult() {
try {
display.value = safeEval(display.value);
calculated = true; // Set flag after calculation
} catch (error) {
display.value = "Error";
}
}
function clearDisplay() {
display.value = "";
calculated = false;
}
// β
Secure Expression Evaluation Function
function safeEval(expression) {
let allowedChars = /^[0-9+\-*/(). ]+$/;
if (!allowedChars.test(expression)) {
throw new Error("Invalid Input");
}
return new Function("return " + expression)();
}
</script>
</body>
</html>
πΉ Best Practice: Ensure secure evaluation using safeEval()
to prevent malicious input execution.
π Project 3: FAQ Accordion (Dynamic UI Component)
An FAQ accordion expands or collapses content when clicked.
πΉ What is an Accordion UI?
An accordion UI hides/show sections dynamically when users interact with them.
π How It Works?
- Each FAQ section has a button.
- Clicking the button toggles the visibility of the answer.
π Code Implementation:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FAQs</title>
<style>
.container {
max-width: 700px;
background-color: gainsboro;
box-shadow: 1px 1px 5px gray;
margin: 50px auto;
padding: 25px;
}
.faq-container {
background-color: #fff;
padding: 15px;
border-radius: 5px;
margin-bottom: 15px;
font-family: Arial, Helvetica, sans-serif;
letter-spacing: 1px;
}
.faq-question {
cursor: pointer;
font-weight: 600;
}
.faq-answer {
max-height: 0;
overflow: hidden;
opacity: 0;
transition: max-height 0.3s ease-out, opacity 0.3s ease-out;
}
.show {
max-height: 100%;
opacity: 1;
margin-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<div class="faq-container">
<div class="faq-question">
What is JavaScript?
</div>
<div class="faq-answer">
JavaScript is a programming language used to create interactive web applications.
</div>
</div>
<div class="faq-container">
<div class="faq-question">
What is the difference between `let`, `const`, and `var`?
</div>
<div class="faq-answer">
`let` and `const` were introduced in ES6. `var` is function-scoped, while `let` and `const` are
block-scoped. `const`
cannot be reassigned.
</div>
</div>
<div class="faq-container">
<div class="faq-question">
What is an event listener in JavaScript?
</div>
<div class="faq-answer">
An event listener is a function that waits for a specific event (like click, hover, etc.) and executes
when that event
occurs.
</div>
</div>
</div>
<script>
document.querySelectorAll('.faq-container').forEach(item => {
item.addEventListener("click", () => {
let answer = item.querySelector('.faq-answer');
answer.classList.toggle('show');
// Keep Rest Items Hide
document.querySelectorAll('.faq-answer').forEach(ans => {
if (ans !== answer) {
ans.classList.remove('show');
}
});
});
});
</script>
</body>
</html>
πΉ Best Practice: Use CSS transitions for smooth animations instead of setting display: block
manually.
π― Conclusion
Building mini projects helps reinforce JavaScript concepts practically! π
β
Key Takeaways:
β Form Validation β Ensures correct user input with real-time feedback.
β Calculator β Performs real-time arithmetic operations.
β FAQ Accordion β Expands/collapses UI content dynamically.
π Try these projects and modify them to enhance your learning!
π¬ Which project did you like the most? Share your thoughts in the comments! π