JSFiddle - React, Tailwind, and code Playground

by graphettion

HTML

<h1>Data Entry Form</h1>
<form id="dataForm" novalidate>
  <div class="form-group">
    <label for="fullName" class="required">Full Name</label>
    <input
      type="text"
      id="fullName"
      name="fullName"
      placeholder="Enter your full name"
      required
    />
    <span class="validation-message" data-error=""></span>
  </div>

  <div class="form-group">
    <label for="email" class="required">Email Address</label>
    <input
      type="email"
      id="email"
      name="email"
      placeholder="Enter your email address"
      required
    />
    <span class="validation-message" data-error=""></span>
  </div>

  <div class="form-group">
    <label for="phone">Phone Number</label>
    <input
      type="tel"
      id="phone"
      name="phone"
      placeholder="Enter your phone number"
    />
    <span class="validation-message" data-error=""></span>
  </div>

  <div class="form-group">
    <label for="age" class="required">Age</label>
    <input
      type="number"
      id="age"
      name="age"
      min="18"
      max="120"
      placeholder="Enter your age"
      required
    />
    <span class="validation-message" data-error=""></span>
  </div>

  <div class="form-group">
    <label for="department" class="required">Department</label>
    <select id="department" name="department" required>
      <option value="">Select a department</option>
      <option value="sales">Sales</option>
      <option value="marketing">Marketing</option>
      <option value="engineering">Engineering</option>
      <option value="hr">Human Resources</option>
      <option value="finance">Finance</option>
    </select>
    <span class="validation-message" data-error=""></span>
  </div>

  <div class="form-group">
    <label for="employeeId" class="required">Employee ID</label>
    <input
      type="text"
      id="employeeId"
      name="employeeId"
      placeholder="Format: EMP-XXXXX"
      required
    />
    <span class="validation-message"...

CSS

body {
  font-family: Arial, sans-serif;
  line-height: 1.6;
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

h1 {
  color: #333;
  border-bottom: 2px solid #eee;
  padding-bottom: 10px;
}

.form-group {
  margin-bottom: 20px;
}

label {
  display: block;
  margin-bottom: 5px;
  font-weight: bold;
}

input,
select,
textarea {
  width: 100%;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
}

button {
  background-color: #4caf50;
  color: white;
  padding: 12px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}

button:hover {
  background-color: #45a049;
}

.success-message {
  background-color: #dff0d8;
  color: #3c763d;
  padding: 15px;
  margin-top: 20px;
  border-radius: 4px;
  display: none;
}

.required:after {
  content: " *";
  color: #ff0000;
}

/* Styling for invalid inputs using the :invalid pseudo-class */
input:invalid,
select:invalid,
textarea:invalid {
  border: 2px solid #ff0000;
  background-color: #ffeeee;
}

/* Style for validation message */
input:invalid + span::after,
select:invalid + span::after,
textarea:invalid + span::after {
  content: attr(data-error);
  color: #ff0000;
  font-size: 14px;
  display: block;
  margin-top: 5px;
}

JavaScript

document.addEventListener("DOMContentLoaded", function () {
  const form = document.getElementById("dataForm")
  const successMessage = document.getElementById("successMessage")

  // Get form elements
  const fullName = document.getElementById("fullName")
  const email = document.getElementById("email")
  const phone = document.getElementById("phone")
  const age = document.getElementById("age")
  const department = document.getElementById("department")
  const employeeId = document.getElementById("employeeId")
  const joinDate = document.getElementById("joinDate")
  const comments = document.getElementById("comments")

  // Function to update error messages based on validity
  function updateErrorMessage(element, message) {
    const span = element.nextElementSibling
    span.setAttribute("data-error", message || "")
  }

  // Validation functions using setCustomValidity
  function validateFullName() {
    const value = fullName.value.trim()

    if (value.length < 2) {
      fullName.setCustomValidity(
        "Please enter your full name (minimum 2 characters)",
      )
      updateErrorMessage(
        fullName,
        "Please enter your full name (minimum 2 characters)",
      )
    } else {
      fullName.setCustomValidity("")
      updateErrorMessage(fullName, "")
    }
  }

  function validateEmail() {
    const value = email.value.trim()
    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/

    if (!emailPattern.test(value)) {
      email.setCustomValidity("Please enter a valid email address")
      updateErrorMessage(email, "Please enter a valid email address")
    } else {
      email.setCustomValidity("")
      updateErrorMessage(email, "")
    }
  }

  function validatePhone() {
    const value = phone.value.trim()

    if (value === "") {
      // Phone is optional
      phone.setCustomValidity("")
      updateErrorMessage(phone, "")
      return
    }

    const phonePattern = /^\d{10}$/
    if (!phonePattern.test(value.replace(/\D/g, ""))) {
  ...