Episode ini membedah validasi form yang canggih: atribut bawaan seperti required dan pattern, tipe input modern beserta inputmode, dan Constraint Validation API untuk validasi lewat JavaScript dengan pesan kustom.

Validasi bukan lagi tugas eksklusif JavaScript. Browser modern punya sistem validasi bawaan yang aktif hanya dengan menulis atribut pada elemen input — cepat, konsisten, dan dikenali screen reader. Episode 17 membahas formulir lanjutan dan validasi browser: atribut seperti required dan pattern, tipe input modern, serta Constraint Validation API untuk kontrol yang lebih presisi.
Validasi di sisi klien mempercepat umpan balik, tapi bukan pengganti validasi di server. Paduan keduanya — validasi browser untuk kenyamanan, validasi server untuk keamanan — adalah pola yang benar dan selalu kalian pakai di proyek nyata.
Atribut paling dasar adalah required, yang memaksa pengguna mengisi bidang tertentu. Pasangkan dengan minlength dan maxlength untuk mengontrol panjang teks:
<form action="/daftar" method="post">
<label for="nama">Nama</label>
<input type="text" id="nama" name="nama" required minlength="3" maxlength="50">
<button type="submit">Kirim</button>
</form>Saat bidang kosong, browser menampilkan pesan bawaan dan menghentikan pengiriman. maxlength bahkan mencegah pengetikan melewati batas — kalian tidak bisa mengetik lebih dari 50 karakter.
Untuk input angka, min, max, dan step membatasi rentang nilai yang diterima:
<label for="usia">Usia</label>
<input type="number" id="usia" name="usia" min="17" max="65" step="1">Form tidak terkirim jika angkanya di luar 17 sampai 65. Atribut ini juga memberi petunjuk bagi kontrol panah naik turun yang disediakan browser.
pattern menerima ekspresi reguler dan cocok untuk format spesifik seperti nomor telepon:
<label for="hp">Nomor HP</label>
<input type="tel" id="hp" name="hp" pattern="[0-9]{10,13}" placeholder="081234567890">Pola regex di atas bermakna angka sepuluh sampai tiga belas digit. Uji pola dengan alat bantu regex sebelum dipakai, karena pesan error bawaan tidak menjelaskan format yang benar.
type="email", type="url", dan type="tel" membuat browser menampilkan keyboard virtual yang sesuai di perangkat mobile — huruf untuk email, papan khusus untuk alamat web.
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="kode">Kode OTP</label>
<input type="text" id="kode" name="kode" inputmode="numeric" maxlength="6">Atribut inputmode="numeric" memunculkan keyboard angka untuk kode OTP tanpa mengubah tipe menjadi number. Gunakan inputmode saat formatnya teks pendek yang diisi angka.
Terkadang form divalidasi lewat JavaScript, misalnya saat mengirim dengan fetch. Constraint Validation API menyediakan metodenya:
const form = document.getElementById("form-daftar");
form.addEventListener("submit", (event) => {
if (!form.checkValidity()) {
event.preventDefault();
form.reportValidity();
return;
}
fetch("/daftar", { method: "POST", body: new FormData(form) });
});form.checkValidity() mengembalikan true atau false. form.reportValidity() menampilkan pesan error bawaan di bidang yang bermasalah. Pasangan ini menjaga umpan balik tetap konsisten dengan validasi browser.
Pesan bawaan berbahasa Inggris dan kadang kurang spesifik. Ganti dengan bahasa yang lebih jelas lewat setCustomValidity:
const kataSandi = document.getElementById("kata-sandi");
kataSandi.addEventListener("input", () => {
if (kataSandi.validity.patternMismatch) {
kataSandi.setCustomValidity("Kata sandi minimal 8 karakter.");
} else {
kataSandi.setCustomValidity("");
}
});Selama setCustomValidity berisi teks bukan kosong, bidang dianggap tidak valid. Kosongkan lagi dengan setCustomValidity("") begitu masalahnya hilang.
Tanpa JavaScript, CSS memberi isyarat visual lewat pseudo-class :valid dan :invalid:
input:invalid {
border-color: #dc2626;
}
input:valid {
border-color: #16a34a;
}Gaya ini tampil segera, bahkan saat halaman baru dimuat. Untuk menampilkan hanya setelah pengguna mencoba mengirim, tambahkan kelas seperti was-validated pada form saat submit lewat JavaScript.
Rangkai semua bahan menjadi satu halaman:
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pendaftaran Kursus</title>
</head>
<body>
<h1>Pendaftaran Kursus</h1>
<form id="form-daftar" action="/daftar" method="post" novalidate>
<label for="nama">Nama lengkap</label>
<input type="text" id="nama" name="nama" required minlength="3">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="usia">Usia</label>
<input type="number" id="usia" name="usia" min="17" max="65">
<label for="hp">Nomor HP</label>
<input type="tel" id="hp" name="hp" pattern="[0-9]{10,13}">
<button type="submit">Daftar Sekarang</button>
</form>
<script src="js/validasi.js"></script>
</body>
</html>Perhatikan atribut novalidate pada form: tanpa itu, browser memvalidasi sebelum event submit berjalan dan JavaScript tidak pernah mendapat giliran. Dengan novalidate, kendali validasi sepenuhnya ada di tangan skrip.
Pattern yang terlalu ketat sering menolak input yang sebenarnya sah, seperti spasi dan tanda hubung pada nomor telepon. Jika format sebenarnya fleksibel, longgarkan polanya atau bersihkan input di server.
Validasi browser bisa dilewati dengan mudah lewat alat pengembang. Selalu validasi ulang di server — data dari klien tidak pernah bisa dipercaya begitu saja.
Episode 17 menyempurnakan form kalian: atribut required, min, max, dan pattern, tipe input modern dengan inputmode, serta Constraint Validation API untuk validasi lewat JavaScript dengan pesan kustom.
Inti yang harus dibawa pulang:
pattern memakai regex untuk format khusus seperti nomor telepon.inputmode memicu keyboard yang tepat di perangkat mobile.checkValidity dan reportValidity bekerja berpasangan lewat JavaScript.setCustomValidity mengganti pesan error dengan bahasa yang jelas.Di episode 18 selanjutnya kita akan membahas template HTML dan shadow DOM dasar — elemen template untuk menyimpan markup yang belum dirender dan cara membungkus komponen dengan shadow DOM agar gaya serta strukturnya terisolasi.