Swap out of band (OOB, "di luar jalur utama") membuat satu balasan server memperbarui beberapa bagian halaman sekaligus: target utama seperti biasa, plus potongan lain yang menandai dirinya dengan hx-swap-oob dan dicocokkan lewat id. Bayangin kurir yang mengantar satu bungkusan ke meja kasir Laundry Bu Rini. Isi utamanya ditaruh di meja. Tapi di dalamnya ada dua amplop berlabel: "untuk papan jumlah order" dan "untuk kotak ringkasan". Kasir mengantar tiap amplop ke tempat yang namanya tertulis di labelnya. Label itu id, dan tulisan "antar sendiri" itu hx-swap-oob.
🧪 Tebakan cepat: Balasan
POST /orderberisi<li id="order-15">lalu<span id="jumlah-hari-ini">4 order hari ini</span>, tanpahx-swap-oob. Di mana span itu berakhir? Jawabannya ada di bagian "Tanpa hx-swap-oob".
Satu order, tiga tempat berubah
Halaman papan punya penghitung di header, kotak ringkasan, dan papan order:
<header>Laundry Bu Rini · <span id="jumlah-hari-ini">3 order hari ini</span></header>
<div id="ringkasan"><p>3 order aktif, 1 siap diambil</p></div>
<ul id="papan-order">...</ul>
<form id="terima" hx-post="/order" hx-target="#papan-order" hx-swap="beforeend">
<input name="nama"> <input name="berat"> <button>Terima cucian</button>
</form>
Begitu Bu Tini masuk, ketiganya harus berubah. Target form cuma satu, #papan-order. Tanpa OOB, kamu butuh tiga request.
hx-swap-oob="true"
Server membalas baris order baru, ditambah dua potongan bertanda:
<li id="order-15">#15 Bu Tini, 4 kg: <span>Antre</span></li>
<span id="jumlah-hari-ini" hx-swap-oob="true">4 order hari ini</span>
<div id="ringkasan" hx-swap-oob="true"><p>4 order aktif, 1 siap diambil</p></div>
| Langkah | Yang dilakukan htmx |
|---|---|
| 1 | mencari elemen ber-hx-swap-oob di balasan, lalu mengeluarkannya |
| 2 | untuk tiap potongan, mencari elemen dengan id yang sama di halaman, lalu menukar seluruh elemennya (outerHTML). Atribut hx-swap-oob dibuang |
| 3 | sisa balasan, yaitu <li>, masuk ke hx-target dengan hx-swap-nya sendiri: beforeend di #papan-order |
Hasilnya: header jadi "4 order hari ini", ringkasan jadi "4 order aktif, 1 siap diambil", dan #15 ada di akhir papan. Satu request. Urutan potongan di balasan gak penting.
Tanpa hx-swap-oob
Span tanpa tanda dianggap bagian dari isi utama. Jadi span itu ikut masuk ke #papan-order, di belakang <li id="order-15">, dan sekarang ada dua elemen ber-id jumlah-hari-ini. Header-nya masih "3 order hari ini". Itu jawaban tebakannya.
Cara tukar yang lain
hx-swap-oob |
Hasilnya |
|---|---|
true |
seluruh elemen dengan id sama ditukar (outerHTML) |
innerHTML |
elemennya tetap, cuma isinya yang ditukar |
beforeend:#papan-order |
isi potongan itu ditambahkan di akhir #papan-order. Pembungkusnya sendiri gak ikut |
Contoh beforeend:#papan-order: form yang targetnya nota bisa sekaligus menambah baris di papan. Balasannya <p>Tanda terima #15</p> untuk #nota, plus <ul hx-swap-oob="beforeend:#papan-order"><li id="order-15">...</li></ul>. Yang masuk ke papan cuma <li>-nya.
Bandingkan dengan hx-select-oob dari pelajaran hx-select: di sana elemen di halaman yang memilih bagian dari balasan. Di sini server yang menandai potongannya di balasan.
Kalau id-nya gak ada, atau balasannya cuma potongan OOB
- Potongan dengan id yang gak ada di halaman, misalnya
id="total-kg", dibuang. htmx memicuhtmx:oobErrorNoTargetdan menulisnya di Console. Gak ada yang muncul di halaman. - Balasan yang cuma berisi potongan OOB menyisakan isi utama kosong, dan kekosongan itu tetap ditaruh di target. Dengan
innerHTML, targetnya jadi kosong. Pakaihx-swap="none"di elemen yang mengirim, supaya cuma potongan OOB yang ditukar. - Balasan 4xx dan 5xx gak ditukar sama sekali, termasuk potongan OOB di dalamnya.
⚠️ Jebakan yang sering ketemu
- Lupa
hx-swap-oob. Potongan itu masuk ke target utama, dan id-nya jadi ganda. - Id di balasan beda dengan di halaman.
jumlah-hariinigak cocok denganjumlah-hari-ini: potongannya dibuang tanpa terlihat. Cek Console. - Balasan cuma OOB dengan target
innerHTML. Target-nya terhapus. Tambahkanhx-swap="none". - Atributnya di tempat yang salah di latihan.
hx-swap-oob="true"dipasang di potongan dalam<template id="contoh-balasan">, bukan di tombol. Tombolnya butuhhx-post="/api/items"danhx-swap="beforeend", atau di latihan keduahx-post="/api/mark-read"danhx-target="#result".
TL;DR: OOB (out of band) membuat satu balasan memperbarui beberapa bagian halaman. Potongan di balasan yang punya hx-swap-oob="true" dikeluarkan, lalu menukar elemen dengan id yang sama di halaman (outerHTML). Sisanya masuk ke hx-target seperti biasa. innerHTML cuma menukar isinya, beforeend:#papan-order menambahkan isinya ke elemen lain. Tanpa tanda, potongan itu ikut masuk ke target dan id-nya ganda. Id yang gak ada membuat potongannya dibuang (htmx:oobErrorNoTarget), dan balasan yang cuma berisi OOB butuh hx-swap="none".