Kodeloka
  1. Kodeloka
  2. Kelas HTML
  3. Materi

3 · Formulir · Modul 15 dari 27

Formulir Web dan Kontrol Masukan Modern

Membangun formulir HTML yang ergonomis dan aksesibel menggunakan <form>, <label>, <fieldset>, beragam tipe <input> modern, <select>, <datalist>, <textarea>, serta memahami cara kerja pengiriman data (GET vs POST).

Bagaimana Formulir Mengirimkan Data ke Server?

Formulir (<form>) adalah jembatan utama bagi pengguna untuk mengirimkan data ke server—mulai dari kotak pencarian, halaman masuk (login), hingga pendaftaran akun dan transaksi pembayaran.

Tiga atribut paling mendasar pada <form> adalah:

  1. action: Alamat URL tujuan tempat data formulir akan dikirimkan (misalnya action="/api/pendaftaran").
  2. method: Metode HTTP yang digunakan saat mengirim data:
    • GET: Data dirangkai ke dalam query string di URL (contoh: /cari?q=golang&tingkat=dasar). Gunakan GET hanya untuk aksi pengambilan/penyaringan data yang bersifat idempoten (tidak mengubah data di server) dan tidak mengandung informasi rahasia seperti kata sandi.
    • POST: Data dikirim di dalam tubuh permintaan (request body) HTTP, tidak terlihat di bilah alamat URL. Gunakan POST untuk semua aksi yang membuat, mengubah, menghapus data, mengirim berkas, atau memuat data sensitif.
    • dialog: Nilai khusus untuk <form method="dialog"> yang berada di dalam elemen <dialog>; alih-alih mengirim data ke server, pengiriman formulir akan menutup kotak dialog tersebut.
  3. enctype: Cara data dikodekan di dalam body saat menggunakan method="POST":
    • application/x-www-form-urlencoded (bawaan): Pasangan name=value yang dikodekan URL.
    • multipart/form-data: Wajib digunakan apabila di dalam formulir terdapat <input type="file"> untuk mengunggah berkas!

1. Aturan Wajib: Setiap Kontrol Harus Memiliki <label> dan name

Dua kesalahan paling fatal saat membuat formulir adalah melupakan <label> dan melupakan atribut name:

  • Tanpa <label> yang terhubung dengan for="id-input": Pengguna pembaca layar tidak tahu apa yang harus diketik di dalam kotak input tersebut. Selain itu, <label> memperluas area klik/sentuh: saat pengguna mengeklik teks label (sangat membantu untuk <input type="checkbox"> atau radio yang berukuran kecil di ponsel), fokus otomatis masuk ke kontrol inputnya!
  • Tanpa atribut name: Saat tombol Submit ditekan, peramban menyusun paket data berdasarkan pasangan name=value. Input yang tidak memiliki atribut name tidak akan pernah dikirimkan ke server!
<!-- SALAH: Mengandalkan placeholder sebagai pengganti label, dan lupa atribut name -->
<input type="email" placeholder="Masukkan alamat surel Anda">

<!-- BENAR: Memiliki <label for="...">, id, name, dan autocomplete yang jelas -->
<div class="kelompok-input">
  <label for="surel-pengguna">Alamat Surel</label>
  <input
    type="email"
    id="surel-pengguna"
    name="email"
    autocomplete="email"
    placeholder="[email protected]"
    required
  >
</div>
⚠️ Kesalahan Umum: Menjadikan placeholder sebagai Pengganti <label>

Teks placeholder hilang begitu pengguna mulai mengetik satu huruf, sehingga pengguna mudah lupa format atau tujuan kolom yang sedang diisi. Lebih buruk lagi, teks placeholder umumnya memiliki kontras warna abu-abu rendah yang sulit dibaca. Gunakan <label> untuk judul kolom, dan gunakan placeholder hanya untuk contoh singkat format isian.

2. Memilih Tipe <input> yang Tepat

Memilih atribut type yang spesifik pada <input> memberikan dua keuntungan besar secara gratis: papan ketik virtual yang sesuai di ponsel (misalnya papan ketik khusus angka atau tombol @ untuk surel) dan validasi format otomatis oleh peramban.

Nilai typeFungsi & Keuntungan di Perangkat SelulerAtribut Pendukung Utama
textTeks satu baris umumminlength, maxlength, pattern, spellcheck
emailAlamat surel (menampilkan tombol @ di papan ketik ponsel)multiple, autocomplete="email"
passwordKata sandi (menyembunyikan karakter ketikan)autocomplete="current-password" atau "new-password"
searchKotak pencarian (menyediakan tombol × untuk menghapus isi)inputmode="search"
telNomor telepon (memunculkan papan ketik telepon numerik)inputmode="tel", pattern, autocomplete="tel"
urlAlamat URL lengkap dengan skema (https://...)inputmode="url"
numberAngka matematis dengan batasan rentang (mis. jumlah barang)min, max, step
rangePenggeser nilai (slider)min, max, step
date / datetime-local / timePemilih tanggal dan waktu bawaan sistem operasimin, max, step
checkboxPilihan centang (boleh memilih nol, satu, atau banyak)checked, value
radioPilihan tunggal dari satu kelompok yang memiliki name samachecked, value, required
filePemilihan berkas dari perangkat atau kamera ponselaccept="image/png,image/webp", multiple, capture
hiddenData tersembunyi (seperti token CSRF atau ID item)name, value
💡 Tips Praktis: Kode OTP dan Nomor Kartu Bukanlah type="number"!

Kode OTP ("048291"), kode pos ("01234"), atau nomor kartu identitas bukanlah angka untuk dijumlahkan, melainkan deretan digit yang bisa diawali angka nol (0). Jika Anda memakai type="number", angka 0 di depan bisa hilang, muncul tombol panah atas/bawah yang tidak relevan, dan guliran roda tetikus (scroll wheel) dapat mengubah angkanya secara tidak sengaja! Solusi terbaiknya adalah menggunakan type="text" yang dipadukan dengan inputmode="numeric" dan pattern="[0-9]*":

<label for="kode-otp">Kode Verifikasi 6 Digit</label>
<input
  type="text"
  id="kode-otp"
  name="otp"
  inputmode="numeric"
  pattern="[0-9]{6}"
  maxlength="6"
  autocomplete="one-time-code"
  required
>

3. Mengelompokkan Pilihan dengan <fieldset>, <legend>, <select>, dan <datalist>

<fieldset> dan <legend> untuk Radio & Checkbox

Ketika Anda membuat serangkaian tombol radio (type="radio") atau kotak centang (type="checkbox"), setiap pilihan memiliki <label>-nya sendiri (misalnya "Dasar", "Menengah", "Lanjut"). Namun, bagaimana pembaca layar mengetahui pertanyaan utama dari kelompok pilihan tersebut? Jawabannya adalah membungkusnya dengan <fieldset> dan menulis pertanyaannya di dalam <legend>:

<fieldset>
  <legend>Pilih Tingkat Kesulitan Kelas</legend>

  <div>
    <input type="radio" id="tingkat-dasar" name="tingkat" value="dasar" checked>
    <label for="tingkat-dasar">Dasar (Pemula murni)</label>
  </div>

  <div>
    <input type="radio" id="tingkat-menengah" name="tingkat" value="menengah">
    <label for="tingkat-menengah">Menengah (Sudah paham dasar web)</label>
  </div>

  <div>
    <input type="radio" id="tingkat-lanjut" name="tingkat" value="lanjut">
    <label for="tingkat-lanjut">Lanjut (Siap produksi)</label>
  </div>
</fieldset>

<select> vs <datalist>

  • Gunakan <select> (bersama <option> dan <optgroup>) ketika pengguna wajib memilih salah satu opsi yang sudah ditentukan (misalnya memilih provinsi atau metode pembayaran).
  • Gunakan <datalist> yang dikaitkan ke <input list="..."> ketika Anda ingin memberikan **saran pelengkapan otomatis (autocomplete suggestions)**, tetapi tetap membebaskan pengguna mengetikkan nilai baru yang tidak ada di daftar:
<label for="pilihan-distro">Distribusi Linux yang Anda Gunakan</label>
<input id="pilihan-distro" name="distro" list="daftar-distro" placeholder="Ketik atau pilih...">
<datalist id="daftar-distro">
  <option value="Ubuntu Server 24.04 LTS"></option>
  <option value="Debian 13 (Trixie)"></option>
  <option value="Rocky Linux 9"></option>
  <option value="Arch Linux"></option>
</datalist>

<textarea> dan <output>

  • <textarea>: Untuk masukan teks multi-baris seperti komentar atau alamat lengkap. Berbeda dengan <input>, nilai awal <textarea> ditulis di antara tag pembuka dan penutup (<textarea name="pesan" rows="4">Isi awal</textarea>).
  • <output>: Elemen semantik untuk menampilkan hasil perhitungan dari masukan pengguna (dan secara otomatis memiliki perilaku live region untuk pembaca layar).

Latihan Praktik: Merancang Formulir Pendaftaran Workshop Kodeloka

Buatlah berkas formulir-workshop.html yang mengirimkan data ke /daftar-workshop dengan metode POST dan mengizinkan pengunggahan berkas:

  1. Kolom Nama Lengkap (text, autocomplete="name") dan Alamat Surel (email, autocomplete="email").
  2. Kolom Kode Voucher 5 digit angka menggunakan kombinasi type="text", inputmode="numeric", dan pattern.
  3. Kelompok pilihan sesi waktu (Pagi atau Malam) menggunakan <fieldset>, <legend>, dan <input type="radio">.
  4. Kolom unggah bukti pendaftaran menggunakan <input type="file" accept="image/png,image/jpeg,application/pdf">.
  5. Tombol <button type="submit">Daftar Sekarang</button> dan <button type="reset">Kosongkan</button>.