Infinite Scroll — HTMX

HTMX membuat infinite scroll sangat mudah dengan hx-trigger="revealed". Pattern Post 1 Post 2 Loading more... Server Response (page 2) Post 3 Post 4 Loading…

Infinite scroll memuat halaman berikutnya sendiri saat pengguna menggulir sampai bawah, tanpa tombol "Muat lagi". Di htmx, caranya satu elemen di ujung daftar dengan hx-trigger="revealed": begitu elemen itu terlihat, ia meminta halaman berikutnya. Bayangin Bu Rini menyalin buku riwayat order untuk pelanggan, lima baris per lembar. Di baris terakhir lembar yang sedang dibaca, ia menyelipkan pembatas. Begitu matamu sampai di pembatas itu, lembar berikutnya diambilkan dan ditaruh di bawahnya, dengan pembatas baru di ujungnya. Lembar terakhir datang tanpa pembatas: selesai.

🧪 Tebakan cepat: Riwayat order Bu Rini berisi 11 order lama, 5 per halaman. Halaman 1 ikut termuat bersama halamannya. Kamu menggulir sampai habis. Berapa request yang dikirim htmx? Jawabannya ada di bagian "Berhenti di halaman terakhir".

Baris terakhir yang memicu

<ul id="riwayat">
  <li id="order-11">#11 Bu Sari, 2 kg: <span>Diambil</span></li>
  <li id="order-10">#10 Pak Joko, 4 kg: <span>Diambil</span></li>
  <li id="order-9">#9 Mbak Tia, 3 kg: <span>Diambil</span></li>
  <li id="order-8">#8 Bu Ani, 6 kg: <span>Diambil</span></li>
  <li id="order-7" hx-get="/riwayat?page=2" hx-trigger="revealed" hx-swap="afterend">
    #7 Mas Dodi, 2 kg: <span>Diambil</span>
  </li>
</ul>

Server membalas GET /riwayat?page=2 dengan lima baris berikutnya, dan baris terakhirnya membawa pemicu untuk halaman 3:

<li id="order-6">#6 Bu Wati, 5 kg: <span>Diambil</span></li>
...
<li id="order-2" hx-get="/riwayat?page=3" hx-trigger="revealed" hx-swap="afterend">#2 Pak Ujang, 3 kg: <span>Diambil</span></li>

Berhenti di halaman terakhir

Kamu menggulir sampai Request Baris di daftar
(halaman dibuka) belum ada, halaman 1 ikut halamannya 5
#7 GET /riwayat?page=2 10
#2 GET /riwayat?page=3 11
#1 gak ada, #1 gak punya hx-get 11

Halaman 3 cuma berisi #1, dan server gak memberinya pemicu. Gak ada pemicu lagi, jadi request berhenti: total 2 request. Itu jawaban tebakannya. Di Laravel, pemicu ditulis cuma kalau masih ada halaman: @if ($orders->hasMorePages()), dengan alamat dari $orders->nextPageUrl().

Pola sentinel: elemen "Memuat..." yang mengganti dirinya

<ul id="riwayat">
  ...lima baris...
  <li hx-get="/riwayat?page=2" hx-trigger="revealed" hx-swap="outerHTML">Memuat...</li>
</ul>

revealed atau intersect

⚠️ Jebakan yang sering ketemu

TL;DR: Infinite scroll di htmx: elemen di ujung daftar dengan hx-get="/riwayat?page=2" dan hx-trigger="revealed", yang terpicu sekali saat terlihat. Pakai hx-swap="afterend" di baris terakhir (balasan masuk sesudahnya), atau sentinel "Memuat..." dengan hx-swap="outerHTML" (sentinel-nya diganti). Setiap balasan membawa pemicu baru untuk halaman berikutnya, kecuali halaman terakhir: di situ request berhenti. Tanpa hx-swap, baris baru masuk ke dalam pemicu. Di dalam kotak scroll, revealed gak jalan: pakai intersect once.

Yang akan kamu pelajari