Formulir tanpa aturan isian akan terus mengirim data yang tidak lengkap, lalu membebani server untuk memeriksa ulang semuanya. HTML native menyediakan lapisan pemeriksaan pertama yang berjalan sebelum data meninggalkan browser: kita menuliskan aturan sebagai atribut pada tiap kontrol, dan browser menegakkannya secara otomatis lengkap dengan pesan kesalahan miliknya. Bagian kedua proyek ini menambahkan atribut validasi pada struktur dari Bagian 1, tanpa mengubah satu pun label maupun kelompoknya.

Pemetaan Atribut per Kolom #

Sebelum membaca filenya, perhatikan aturan yang kita tetapkan untuk setiap isian:

KolomAtributAturan yang ditegakkan
Nama lengkaprequired, minlength="3", maxlength="40", pattern="[A-Za-z .]+"Wajib, 3-40 karakter, hanya huruf spasi dan titik
Tanggal lahirrequired, min, maxWajib, lahir antara 1950 dan 2010
Kota domisilirequiredSalah satu opsi harus dipilih
Kategori pesertarequired pada radio pertamaSatu grup harus dipilih
Emailrequired + type="email"Wajib dan berformat email
Kata sandirequired, minlength="8"Wajib, minimal 8 karakter
PersetujuanrequiredCheckbox harus dicentang

Dua catatan dari tabel di atas. Pertama, atribut required pada satu radio saja cukup untuk mewajibkan seluruh grup name="kategori" — validasi radio dinilai per grup, bukan per tombol. Kedua, maxlength mencegah ketikan berlebih sejak ketukan pertama, sedangkan minlength baru diperiksa saat pengiriman; keduanya melengkapi, bukan menggantikan.

File formulir-validasi.html #

Simpan file berikut sebagai formulir-validasi.html di folder bagian-2/:

<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Pendaftaran Seminar Web Komunitas</title>
</head>
<body>
  <main>
    <h1>Pendaftaran Seminar Web Komunitas</h1>
    <p><img src="../assets/logo-acara.svg" alt="Logo Seminar Web Komunitas" width="96" height="96"></p>
    <p>Isi formulir berikut untuk mengikuti acara pada Sabtu, 8 Maret 2025, di Gedung Belajar Kota.</p>
    <form action="www.example.com/daftar" method="post">
      <fieldset>
        <legend>Data diri</legend>
        <p>
          <label for="nama">Nama lengkap</label>
          <input type="text" id="nama" name="nama" autocomplete="name" required minlength="3" maxlength="40" pattern="[A-Za-z .]+" title="Hanya huruf, spasi, dan titik">
        </p>
        <p>
          <label for="tanggal-lahir">Tanggal lahir</label>
          <input type="date" id="tanggal-lahir" name="tanggal-lahir" autocomplete="bday" required min="1950-01-01" max="2010-12-31">
        </p>
        <p>
          <label for="kota">Kota domisili</label>
          <select id="kota" name="kota" autocomplete="address-level2" required>
            <option value="">-- Pilih kota --</option>
            <option value="bandung">Bandung</option>
            <option value="jakarta">Jakarta</option>
            <option value="surabaya">Surabaya</option>
            <option value="yogyakarta">Yogyakarta</option>
          </select>
        </p>
      </fieldset>
      <fieldset>
        <legend>Kategori peserta</legend>
        <p>
          <input type="radio" id="kategori-pelajar" name="kategori" value="pelajar" required>
          <label for="kategori-pelajar">Pelajar</label>
        </p>
        <p>
          <input type="radio" id="kategori-mahasiswa" name="kategori" value="mahasiswa">
          <label for="kategori-mahasiswa">Mahasiswa</label>
        </p>
        <p>
          <input type="radio" id="kategori-profesional" name="kategori" value="profesional">
          <label for="kategori-profesional">Profesional</label>
        </p>
      </fieldset>
      <fieldset>
        <legend>Akun</legend>
        <p>
          <label for="email">Email</label>
          <input type="email" id="email" name="email" autocomplete="email" required>
        </p>
        <p>
          <label for="kata-sandi">Kata sandi</label>
          <input type="password" id="kata-sandi" name="kata-sandi" autocomplete="new-password" required minlength="8">
        </p>
      </fieldset>
      <p>
        <input type="checkbox" id="persetujuan" name="persetujuan" value="setuju" required>
        <label for="persetujuan">Saya menyetujui penggunaan data untuk keperluan acara ini</label>
      </p>
      <button type="submit">Kirim pendaftaran</button>
    </form>
  </main>
</body>
</html>

Output yang Dihasilkan:

text
Saat tombol "Kirim pendaftaran" ditekan dengan kolom kosong:
  - Browser menampilkan gelembung pesan pada kolom pertama yang tidak sah,
    misalnya "Please fill out this field" (kalimat mengikuti bahasa browser)
  - Data tidak dikirim dan halaman tetap terbuka
Saat nama diisi "Bu" lalu tombol ditekan:
  - Gelembung pesan menyatakan isian terlalu pendek
Saat seluruh isian sah:
  - Browser mengirim data ke alamat action dan berpindah sesuai responsnya

Mari kita bedah atribut-atribut barunya:

  1. required: kolom wajib. Bila kosong saat submit, browser memblokir pengiriman, memfokuskan kolom tersebut, dan menampilkan gelembung pesan bawaan.
  2. minlength dan maxlength: batas panjang karakter untuk kontrol teks. Pada kata sandi, minlength="8" menuntut minimal delapan karakter sebelum isian dianggap sah.
  3. pattern: aturan pola dengan ekspresi reguler. Nilai [A-Za-z .]+ menerima huruf besar-kecil, spasi, dan titik; atribut title yang menyertainya dijadikan teks saran browser ketika pola tidak terpenuhi.
  4. min dan max pada type="date": rentang tanggal yang diterima. Isian di luar rentang — misalnya tahun 2030 — mendapat pesan kesalahan tanpa satu baris JavaScript pun.
  5. autocomplete: token yang menjelaskan maksud kolom bagi browser. Token name dan email memungkinkan pengisian otomatis dari data profil; new-password menyatakan kolom ini untuk kata sandi baru sehingga pengelola sandi bisa menawarkannya; bday dan address-level2 menyatakan tanggal lahir serta kota. Bagian ini juga kenyamanan aksesibilitas: banyak pembaca layar membaca maksud kolom dari token ini.
  6. type="email": selain menampilkan keyboard khusus di perangkat sentuh, jenis ini memicu pemeriksaan format — isian tanpa tanda @ ditolak.

Pemeriksaan native berjalan pada momen submit: browser menandai kontrol tidak sah satu per satu, menghentikan pengiriman pada yang pertama, dan tidak membuat permintaan jaringan sama sekali. Atribut novalidate yang terpasang pada elemen form mematikan perilaku ini seluruhnya — kita belum memakainya di sini, tetapi Bagian 4 memasangnya saat JavaScript mengambil alih penyajian pesan.

Langkah Pemeriksaan #

Tuntaskan Bagian ini dengan urutan berikut:

  1. Buka formulir-validasi.html di browser, tekan tombol kirim dengan formulir kosong, dan amati gelembung pesan pada kolom nama. Isi nama dengan “Bu”, tekan kirim lagi, dan amati pesan panjang minimal.
  2. Uji pola nama dengan mengisi angka, lalu uji tanggal lahir di luar rentang (misalnya 2030-01-01) untuk melihat pesan rentang.
  3. Jalankan ../tests/cek-struktur.html dan centang seluruh butir kelompok Validasi atribut.

Seluruh aturan kini bertumpu pada pesan bawaan browser yang kalimat dan posisinya di luar kendali kita. Bagian 3 memberi formulir pakaian yang rapi, sebelum Bagian 4 mengambil alih pesan kesalahan dengan JavaScript.

Referensi resmi untuk pendalaman:

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

formulir-validasi.html

Unduh berkas
html
<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Pendaftaran Seminar Web Komunitas</title>
</head>
<body>
  <main>
    <h1>Pendaftaran Seminar Web Komunitas</h1>
    <p><img src="../assets/logo-acara.svg" alt="Logo Seminar Web Komunitas" width="96" height="96"></p>
    <p>Isi formulir berikut untuk mengikuti acara pada Sabtu, 8 Maret 2025, di Gedung Belajar Kota.</p>
    <form action="www.example.com/daftar" method="post">
      <fieldset>
        <legend>Data diri</legend>
        <p>
          <label for="nama">Nama lengkap</label>
          <input type="text" id="nama" name="nama" autocomplete="name" required minlength="3" maxlength="40" pattern="[A-Za-z .]+" title="Hanya huruf, spasi, dan titik">
        </p>
        <p>
          <label for="tanggal-lahir">Tanggal lahir</label>
          <input type="date" id="tanggal-lahir" name="tanggal-lahir" autocomplete="bday" required min="1950-01-01" max="2010-12-31">
        </p>
        <p>
          <label for="kota">Kota domisili</label>
          <select id="kota" name="kota" autocomplete="address-level2" required>
            <option value="">-- Pilih kota --</option>
            <option value="bandung">Bandung</option>
            <option value="jakarta">Jakarta</option>
            <option value="surabaya">Surabaya</option>
            <option value="yogyakarta">Yogyakarta</option>
          </select>
        </p>
      </fieldset>
      <fieldset>
        <legend>Kategori peserta</legend>
        <p>
          <input type="radio" id="kategori-pelajar" name="kategori" value="pelajar" required>
          <label for="kategori-pelajar">Pelajar</label>
        </p>
        <p>
          <input type="radio" id="kategori-mahasiswa" name="kategori" value="mahasiswa">
          <label for="kategori-mahasiswa">Mahasiswa</label>
        </p>
        <p>
          <input type="radio" id="kategori-profesional" name="kategori" value="profesional">
          <label for="kategori-profesional">Profesional</label>
        </p>
      </fieldset>
      <fieldset>
        <legend>Akun</legend>
        <p>
          <label for="email">Email</label>
          <input type="email" id="email" name="email" autocomplete="email" required>
        </p>
        <p>
          <label for="kata-sandi">Kata sandi</label>
          <input type="password" id="kata-sandi" name="kata-sandi" autocomplete="new-password" required minlength="8">
        </p>
      </fieldset>
      <p>
        <input type="checkbox" id="persetujuan" name="persetujuan" value="setuju" required>
        <label for="persetujuan">Saya menyetujui penggunaan data untuk keperluan acara ini</label>
      </p>
      <button type="submit">Kirim pendaftaran</button>
    </form>
  </main>
</body>
</html>