Atribut required, minlength, min/max, dan pattern yang kita pasang selama ini ternyata bukan aturan yang berdiri sendiri-sendiri. Seluruhnya menyatu dalam satu mekanisme resmi bernama constraint validation — pemeriksaan batasan yang dijalankan browser secara otomatis. Chapter ini menuntun kita melihat mekanisme tersebut dari luar: kapan pemeriksaan berjalan, apa yang terjadi ketika nilai gagal, dan bagaimana mematikannya bila kita ingin mengambil alih.

Cara Browser Memeriksa Form #

Pemeriksaan berjalan mengikuti alur yang tetap:

  1. Pengunjung menekan tombol submit atau menekan Enter di dalam form.
  2. Browser menelusuri setiap kontrol form dan menilai seluruh batasannya: kosong atau tidak, panjang, rentang, dan pola.
  3. Bila semuanya sah, pengiriman berjalan — data dikirim ke action sesuai method.
  4. Bila ada yang gagal, pengiriman dibatalkan: request tidak pernah dibuat, fokus pindah ke kontrol pertama yang bermasalah, dan balon pesan muncul di dekatnya.

Poin terakhir penting: form yang gagal validasi tidak mengirim apa pun ke server. Tidak ada halaman yang dimuat ulang, tidak ada data yang melintas jaringan. Inilah alasan validasi HTML terasa cepat — seluruhnya terjadi di dalam browser.

Constraint Validation API secara Konsep #

Di balik perilaku itu, browser menyediakan constraint validation API: setiap kontrol menyimpan status keabsahan, method checkValidity() menilai kontrol tersebut, dan objek ValidityState merinci alasan kegagalan — misalnya nilai kosong, terlalu pendek, atau tidak cocok pola. Chapter ini cukup memperkenalkan namanya; pemakaiannya dengan skrip kita bahas pada section HTML dan JavaScript.

Mematikan Validasi dengan novalidate #

Atribut boolean novalidate dipasang pada elemen form dan melewati seluruh pemeriksaan native: form tetap terkirim meski kolom wajib kosong atau pola tidak cocok. Dua situasi yang lazim meminta hal ini: ketika validasi custom dengan JavaScript akan menggantikan pesan bawaan agar pemeriksaan tidak dobel, dan saat kita ingin menguji perilaku server terhadap data yang tidak sah.

formnovalidate pada Tombol #

Pemeriksaan juga dapat dilewati hanya untuk satu tombol. Tombol submit yang membawa atribut formnovalidate mengirim form tanpa pemeriksaan, sementara tombol lain pada form yang sama tetap menjalankannya. Pola ini cocok untuk tombol “Simpan draf”: draf boleh lengkap ataupun tidak, tanpa perlu membebani pengunjung dengan pesan kesalahan.

Pseudo-class :valid, :invalid, dan :required #

Browser juga menandai status tiap kontrol lewat pseudo-class CSS: :valid dan :invalid menyala sesuai hasil pemeriksaan, sedangkan :required menandai kolom wajib. Lewat CSS, kolom yang belum sah dapat dibedakan tampilannya sebelum pengunjung menekan tombol. Pembahasan styling-nya menunggu section HTML dan CSS; untuk kini cukup tahu bahwa status validasi terbaca langsung dari markup.

Contoh: Satu Halaman, Dua Perilaku #

File berikut memuat dua form yang identik isinya. Form pertama menjalankan validasi native dan menyediakan tombol draf ber-formnovalidate; form kedua membawa novalidate sehingga seluruh pemeriksaan dimatikan. Simpan sebagai contoh-validasi-browser.html, lalu uji kedua tombolnya dalam keadaan kosong:

<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Dua Perilaku Validasi</title>
</head>
<body>
  <h1>Kirim Pesan ke Redaksi</h1>
  <h2>Form dengan validasi native</h2>
  <form action="/pesan" method="post">
    <p>
      <label for="email-a">Email</label>
      <input type="email" id="email-a" name="email" required>
    </p>
    <p>
      <input type="submit" value="Kirim pesan">
      <button type="submit" name="draf" value="1" formnovalidate>Simpan draf</button>
    </p>
  </form>
  <h2>Form dengan novalidate</h2>
  <form action="/pesan" method="post" novalidate>
    <p>
      <label for="email-b">Email</label>
      <input type="email" id="email-b" name="email" required>
    </p>
    <p>
      <input type="submit" value="Kirim pesan">
    </p>
  </form>
</body>
</html>

Output yang Dihasilkan:

text
Jendela browser menampilkan:
  - Form pertama: klik "Kirim pesan" dalam keadaan kosong memunculkan bubble
    dan membatalkan pengiriman; klik "Simpan draf" tetap mengirim data
  - Form kedua: klik "Kirim pesan" dalam keadaan kosong tetap mengirim,
    tanpa bubble apa pun

Berikut peran setiap bagian kode:

  1. Baris 11-14 (form pertama): form tanpa novalidate; kolom email wajib dan diperiksa saat tombol Kirim pesan ditekan.
  2. Baris 18 (button formnovalidate): tombol Simpan draf mengirim tanpa pemeriksaan, meski kolom email masih kosong; hanya tombol ini yang bebas aturan.
  3. Baris 22 (form kedua): atribut novalidate mematikan pemeriksaan native; required pada baris 25 tetap tertulis di markup tetapi tidak dieksekusi.
  4. Baris 17-18 versus 28: kedua form memakai action dan method yang sama, sehingga perbedaan hasilnya murni berasal dari validasi native.

Selama pemeriksaan berjalan, pengunjung hanya melihat satu wajah dari mekanisme ini: balon pesan kesalahan. Chapter berikutnya membahas pesan tersebut secara khusus — dari mana teksnya berasal dan apa batas-batasnya.

Referensi resmi untuk pendalaman:

Berkas Sumber

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

contoh-validasi-browser.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>Dua Perilaku Validasi</title>
</head>
<body>
  <h1>Kirim Pesan ke Redaksi</h1>
  <h2>Form dengan validasi native</h2>
  <form action="/pesan" method="post">
    <p>
      <label for="email-a">Email</label>
      <input type="email" id="email-a" name="email" required>
    </p>
    <p>
      <input type="submit" value="Kirim pesan">
      <button type="submit" name="draf" value="1" formnovalidate>Simpan draf</button>
    </p>
  </form>
  <h2>Form dengan novalidate</h2>
  <form action="/pesan" method="post" novalidate>
    <p>
      <label for="email-b">Email</label>
      <input type="email" id="email-b" name="email" required>
    </p>
    <p>
      <input type="submit" value="Kirim pesan">
    </p>
  </form>
</body>
</html>