Form dengan hx-post mengirim isinya lewat htmx, tanpa memuat ulang halaman, lalu balasan HTML-nya ditaruh di target. Pelajaran ini membahas tiga hal yang sering bikin bingung: field mana yang ikut terkirim, cara membawa field dari luar form dengan hx-include, dan cara mengosongkan form sesudah berhasil dengan hx-on::after-request. Bayangin nota di meja Laundry Bu Rini. Cuma kotak bernama di dalam nota yang disalin ke buku order. Catatan di kertas tempel di sebelah nota tertinggal, kecuali kamu menjepretnya ke nota. Begitu order tercatat, Bu Rini merobek nota kosong yang baru untuk pelanggan berikutnya.
🧪 Tebakan cepat: Form Terima cucian punya
hx-on::after-request="this.reset()". Kasir lupa mengisi Berat, jadi server menolak dengan 422. Apa yang terjadi pada kotak Nama yang sudah berisi "Bu Tini"? Jawabannya ada di bagian "Mengosongkan form sesudah berhasil".
Form dengan hx-post
<form id="terima" hx-post="/order" hx-target="#papan-order" hx-swap="beforeend">
<input name="nama" placeholder="Nama">
<input name="berat" placeholder="kg">
<label><input type="checkbox" name="express" value="ya"> Express</label>
<button>Terima cucian</button>
</form>
- Menekan Terima cucian, atau Enter di salah satu kotak, mengirim
POST /order. - Body-nya berformat
application/x-www-form-urlencoded, sama dengan form HTML biasa:nama=Bu%20Tini&berat=4. - Server membalas satu baris
<li id="order-15">#15 Bu Tini, 4 kg: <span>Antre</span></li>, danhx-swap="beforeend"menambahkannya di akhir papan. - Validasi browser tetap jalan duluan: kotak
requiredyang kosong membuat request gak dikirim sama sekali.
Field mana yang ikut terkirim
| Field | Ikut terkirim? |
|---|---|
<input name="nama"> di dalam form |
ya |
field tanpa name |
tidak |
field ber-disabled |
tidak |
field ber-readonly |
ya |
| checkbox yang gak dicentang | tidak. Yang dicentang mengirim express=ya (tanpa value: express=on) |
tombol submit yang diklik, kalau punya name |
ya: <button name="layanan" value="kilat"> mengirim layanan=kilat |
field di luar <form> |
tidak, kecuali dibawa hx-include |
hx-include: bawa field dari luar form
Kolom Catatan ada di samping, di luar form. hx-include menjepretnya ke kiriman:
<input id="catatan" name="catatan" value="pakai pewangi">
<form id="terima" hx-post="/order" hx-target="#papan-order" hx-swap="beforeend"
hx-include="#catatan">
...
</form>
- Body-nya jadi
catatan=pakai%20pewangi&nama=Bu%20Tini&berat=4. Di form POST, field yang dibawahx-includeditaruh di depan. - Isinya selector CSS (pakai
#untuk id) atau kata kunci seperticlosest form. Kalau yang ditunjuk sebuah<div>, semua field di dalamnya ikut. - Elemen yang bukan form juga bisa:
<button hx-get="/order" hx-include="#filter">mengirimGET /order?filter=aktif.
Mengosongkan form sesudah berhasil
<form id="terima" hx-post="/order" hx-target="#papan-order" hx-swap="beforeend"
hx-on::after-request="if (event.detail.successful) this.reset()">
hx-on::after-requestmenjalankan JavaScript singkat begitu request selesai. Dua titik dua itu singkatan darihx-on:htmx:after-request.- Di dalamnya,
thisadalah form-nya, danevent.detail.successfulbernilaitruekalau balasannya 2xx. this.reset()saja juga jalan sesudah request gagal. Server membalas 422, dan form tetap dikosongkan: "Bu Tini" ikut hilang, dan kasir harus mengetik ulang semuanya. Itu jawaban tebakannya. Makanya cekevent.detail.successfuldulu.reset()mengembalikan tiap kotak ke nilaivalue="..."di HTML-nya, bukan selalu kosong.<input name="nama" value="Bu Tini">kembali berisi "Bu Tini".- Cara lain: server membalas form kosong yang baru, dengan
hx-target="this"danhx-swap="outerHTML"di form-nya. Form lama tertukar form baru.
Tetap jalan tanpa JavaScript
<form action="/order" method="post"
hx-post="/order" hx-target="#papan-order" hx-swap="beforeend">
Kalau htmx gagal dimuat (koneksi lambat, script terblokir), browser mengirim form ini seperti form biasa ke action-nya, dan server membalas halaman utuh. Dengan htmx, route yang sama cukup membalas satu <li> saat request-nya membawa header HX-Request: true. Inilah progressive enhancement: form-nya tetap berfungsi tanpa JavaScript, dan htmx cuma membuatnya lebih mulus.
⚠️ Jebakan yang sering ketemu
this.reset()tanpa cek sukses. Form dikosongkan juga saat server menolak. Pakaiif (event.detail.successful) this.reset().- Satu titik dua.
hx-on:after-requestmenunggu event bernamaafter-request, yang gak pernah dikirim htmx. Tulis dua:hx-on::after-request. Di latihan, form harus punyahx-on::after-requestyang memeriksaevent.detail.successful,hx-post="/api/items",hx-target="#items", danhx-swap="beforeend". - Lupa
hx-swap="beforeend". BawaannyainnerHTML, jadi item baru menghapus daftar lama. - Field di luar form, atau
hx-includetanpa#.hx-include="filter"mencari tag<filter>, jadi gak ada yang ikut. Di latihan, tombolnya butuhhx-get="/api/todos"danhx-include="#filter".
TL;DR: Form ber-hx-post mengirim field ber-name di dalamnya sebagai application/x-www-form-urlencoded. Field tanpa name, yang disabled, dan checkbox yang gak dicentang gak ikut, tapi tombol submit yang diklik ikut kalau punya name. hx-include="#catatan" membawa field dari luar form. hx-on::after-request="if (event.detail.successful) this.reset()" mengosongkan form cuma sesudah balasan 2xx, karena this.reset() saja juga jalan saat gagal. Tulis juga action dan method, supaya form tetap berfungsi tanpa JavaScript.