hx-select memilih sebagian dari balasan HTML dengan selector CSS, sebelum balasan itu ditaruh di target. Ini berguna saat server membalas halaman penuh, padahal kamu cuma butuh satu bagiannya. Bayangin Bu Rini meminta fotokopi halaman buku order dari cabang lain. Yang datang satu halaman penuh: kop toko, alamat, iklan, dan tabel order. Dia cuma butuh tabelnya, jadi tabel itu digunting lalu ditempel di papan. Guntingnya hx-select. Fotokopinya tetap satu halaman penuh: menggunting gak membuat kiriman jadi lebih tipis.
🧪 Tebakan cepat: Tombol Muat ulang papan punya
hx-get="/papan" hx-target="#papan-order" hx-select="#papan-order", tanpahx-swap. Server membalas halaman/papanpenuh. Sesudah diklik, ada berapa elemen ber-idpapan-orderdi halaman? Jawabannya ada di bagian "Pasangan yang benar".
Masalahnya: server membalas halaman penuh
Route lama Bu Rini membalas GET /papan dengan halaman yang sama seperti saat dibuka:
<!doctype html>
<html lang="id">
<head><title>Papan order | Laundry Bu Rini</title> ...</head>
<body>
<header><h1>Laundry Bu Rini</h1><nav>...</nav></header>
<main id="isi">
<div id="ringkasan"><p>4 order aktif, 1 siap diambil</p></div>
<ul id="papan-order">
<li id="order-12">#12 Pak Darto, 3 kg: <span>Disetrika</span></li>
...
<li id="order-15">#15 Bu Tini, 4 kg: <span>Antre</span></li>
</ul>
<button id="muat-ulang" ...>Muat ulang papan</button>
</main>
<footer>Jl. Melati 5</footer>
</body>
</html>
Tanpa hx-select, htmx membuang <head>-nya lalu menaruh seluruh isi <body> di target. Header, menu, ringkasan, tombol, dan footer muncul di dalam papan order. Judul tab juga ikut diganti <title> dari balasan.
hx-select: ambil bagian yang kamu mau
<button id="muat-ulang" hx-get="/papan" hx-target="#papan-order"
hx-select="#papan-order > li">
Muat ulang papan
</button>
- htmx mencari semua elemen yang cocok dengan
#papan-order > lidi dalam balasan, lalu cuma itu yang ditaruh. Di sini 4<li>. - Semua yang cocok diambil, bukan cuma yang pertama.
hx-selectmembaca balasan,hx-targetmenunjuk tempat di halaman. Keduanya selector CSS, tapi bekerja di dua tempat berbeda.
Pasangan yang benar
hx-select |
hx-swap |
Hasil di halaman |
|---|---|---|
| (gak ada) | innerHTML |
seluruh <body> balasan di dalam papan |
#papan-order |
innerHTML |
<ul> baru di dalam <ul> lama: 2 elemen ber-id papan-order |
#papan-order |
outerHTML |
<ul> lama ditukar <ul> baru: 1 papan, 4 order |
#papan-order > li |
innerHTML |
isi papan ditukar 4 <li> baru: 1 papan, 4 order |
hx-select="#papan-order" memilih seluruh <ul>. Bawaan innerHTML menaruhnya di dalam <ul> yang lama, jadi ada 2 elemen ber-id papan-order, ul di dalam ul. Itu jawaban tebakannya. Kalau yang dipilih elemen yang sama dengan target, pakai outerHTML. Kalau mau tetap innerHTML, pilih isinya: #papan-order > li.
Yang gak berubah: ukuran balasan
hx-select menyaring sesudah balasan tiba. Di Lab, server tetap mengirim halaman penuh, 961 byte, walau yang dipakai cuma papan 310 byte. Jadi hx-select itu kemudahan, bukan penghematan. Untuk balasan yang benar-benar kecil, server membaca header HX-Request: true lalu membalas potongan papannya saja. Di Laravel: if ($request->header('HX-Request')) { return view('papan._order', ...); }.
hx-select-oob: ambil satu bagian lagi
<button id="muat-ulang" hx-get="/papan" hx-target="#papan-order"
hx-select="#papan-order" hx-swap="outerHTML"
hx-select-oob="#ringkasan">
#ringkasan dari balasan yang sama ikut menggantikan #ringkasan di halaman, dicocokkan lewat id-nya. Jadi satu request memperbarui papan dan ringkasan sekaligus. Swap out of band (OOB) dibahas lebih dalam di pelajaran OOB swaps.
⚠️ Jebakan yang sering ketemu
- Elemen yang dipilih sama dengan target, dengan
innerHTML. Hasilnya ul di dalam ul dan id ganda. PakaiouterHTML, atau pilih isinya. - Selector gak cocok dengan apa pun di balasan.
hx-select="#papan-ordr"memilih nol elemen, dan htmx tetap menukar dengan yang kosong: papannya kosong (innerHTML) atau hilang (outerHTML). Gak ada error. hx-selectdi elemen induk. Atribut ini diwariskan, jadi tombol lain di dalamnya ikut menyaring balasannya sendiri dan targetnya jadi kosong. Tulishx-select="unset"di tombol itu, atau taruhhx-selectdi tombol yang butuh saja.- Lupa
hx-get, atau target-nya gak ada. Di latihan, tombolnya butuhhx-get="/page",hx-select="#content", danhx-targetyang menunjuk elemen yang benar-benar ada, yaitu#result.
TL;DR: hx-select="#papan-order" mengambil bagian yang cocok dari balasan, semua yang cocok, sebelum ditaruh di target. Berguna saat server membalas halaman penuh. Kalau yang dipilih elemen yang sama dengan target, pakai hx-swap="outerHTML" (atau pilih isinya, #papan-order > li), supaya gak jadi ul di dalam ul. Selector yang gak cocok mengosongkan target tanpa error, dan hx-select diwariskan ke elemen di dalamnya. hx-select-oob="#ringkasan" mengambil satu bagian lagi berdasarkan id. Ukuran balasan gak berubah: untuk balasan kecil, server membalas potongan saat ada HX-Request: true.