Indikator Loading — HTMX

HTMX menyediakan mekanisme bawaan untuk menampilkan indikator loading (spinner, pesan "memuat", dsb.) tanpa perlu JavaScript tambahan. hx-indicator Load Data…

Indikator loading adalah elemen, misalnya tulisan "Menyimpan..." atau spinner, yang cuma terlihat selama request berjalan. htmx mengaturnya lewat satu class: selama request berjalan, htmx-request dipasang, dan begitu balasan tiba, class itu dilepas. Bayangin meja Laundry Bu Rini. Selama dia mencatat order di buku, dia membalik papan kecil bertuliskan "Sebentar, sedang dicatat", dan bel Terima dia tutup supaya gak ada yang memencetnya dua kali. Papan kecil itu hx-indicator, menutup bel itu hx-disabled-elt.

🧪 Tebakan cepat: Server butuh 1 detik untuk mencatat order. Kasir mengklik Terima cucian dua kali dengan cepat, dan form-nya gak punya hx-disabled-elt. Berapa order Bu Tini yang tercatat? Jawabannya ada di bagian "hx-disabled-elt: cegah klik dua kali".

Class htmx-request dan CSS bawaan htmx

Saat htmx mulai mengirim request, elemen pengirimnya diberi class htmx-request. Saat balasan tiba, class itu dilepas. htmx juga menambahkan CSS ini ke <head> halamanmu secara otomatis:

.htmx-indicator { opacity: 0; visibility: hidden; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { opacity: 1; visibility: visible; transition: opacity 200ms ease-in; }

Jadi spinner di dalam tombol langsung jalan, tanpa atribut tambahan:

<button hx-get="/order/12/status" hx-target="#status-12">
  Cek status <span class="htmx-indicator">memuat...</span>
</button>

Tombolnya diberi htmx-request, dan <span> di dalamnya ikut muncul.

hx-indicator: tunjuk penandanya

Tulisan "Menyimpan..." di meja Bu Rini ada di luar form. Form-nya menunjuk tulisan itu:

<form id="terima" hx-post="/order" hx-target="#nota" hx-indicator="#memuat">
  <input name="nama">
  <input name="berat">
  <button>Terima cucian</button>
</form>
<span id="memuat" class="htmx-indicator">Menyimpan...</span>
<div id="nota"></div>

Dengan server yang membalas dalam 1 detik:

Waktu Class #memuat Yang terlihat
sebelum diklik htmx-indicator tersembunyi
0 ms, Terima ditekan htmx-indicator htmx-request "Menyimpan..." muncul
1.000 ms, balasan tiba htmx-indicator "Menyimpan..." hilang, nota muncul di #nota

hx-disabled-elt: cegah klik dua kali

htmx gak membuang klik kedua yang datang saat request pertama masih berjalan. Ia menahannya, lalu mengirimnya begitu balasan pertama tiba. Jadi klik dua kali mengirim 2 POST, dan server mencatat order #15 dan #16 untuk Bu Tini yang sama. Itu jawaban tebakannya. Klik tiga kali pun tetap 2, karena htmx cuma menyimpan satu antrean, yang terakhir.

<form id="terima" hx-post="/order" hx-target="#nota"
      hx-indicator="#memuat" hx-disabled-elt="find button">

Menghias sendiri dengan htmx-request

Class htmx-request bisa dipakai di CSS-mu sendiri. Contoh, papan order yang polling diredupkan selama menunggu balasan:

#papan-order.htmx-request { opacity: 0.5; }

Di komputermu sendiri server biasanya membalas dalam beberapa milidetik, jadi penandanya cuma berkedip. Untuk mencobanya, pilih "Slow 3G" di tab Network DevTools.

⚠️ Jebakan yang sering ketemu

TL;DR: Selama request berjalan, htmx memasang class htmx-request di elemen pengirimnya, atau di elemen yang ditunjuk hx-indicator="#memuat". CSS bawaan htmx menyembunyikan .htmx-indicator dan memunculkannya saat dia atau induknya memakai htmx-request. Jadi spinner di dalam tombol cukup diberi class htmx-indicator, dan spinner di tempat lain ditunjuk dengan hx-indicator (pakai #). hx-disabled-elt="find button" memasang disabled selama request, supaya klik kedua gak mengirim order kedua. Tanpa itu, klik kedua ditahan lalu tetap dikirim.

Yang akan kamu pelajari