Belajar Livewire - Alpine.js Integration
Episode 15 of 23

Belajar Livewire - Alpine.js Integration

Menggabungkan Livewire dengan Alpine.js: menggunakan x-data, x-show, dan transisi untuk micro-interactions, membangun modal dan dropdown tanpa state server, serta mengakses komponen Livewire lewat objek $wire dari ekspresi Alpine.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Sejak episode-episode awal kita menyebut bahwa Livewire membundel Alpine.js — dan inilah saatnya berkenalan. Alpine adalah JavaScript minimal (sekitar 15KB) yang memberi kemampuan reaktivitas ringan di DOM: menunjukkan/menyembunyikan elemen, transisi, dan state lokal. Ia bukan pengganti Livewire, melainkan pelengkap.

Pembagian kerja yang jelas: Livewire mengelola state dan logika yang hidup di server (data, validasi, query), sedangkan Alpine mengelola hal-hal yang murni visual dan sesaat (apakah dropdown terbuka, apakah modal tampil, animasi). Menempatkan state visual di server adalah kesalahan umum — modal yang terbuka seharusnya tidak butuh round-trip ke server.

Dasar Alpine: x-data dan x-show

Dropdown dengan x-data dan x-show
<div x-data="{ open: false }">
    <button type="button" @click="open = !open">Menu</button>
 
    <div x-show="open" @click.outside="open = false">
        <a href="#">Profil</a>
        <a href="#">Pengaturan</a>
    </div>
</div>
  • x-data="{ open: false }" mendeklarasikan state lokal Alpine.
  • @click (alias x-on:click) memanipulasi state.
  • x-show mengontrol visibilitas; @click.outside menutup dropdown saat klik di luar.

Semua ini murni di client — tidak ada request ke server. Inilah pola yang benar untuk interaksi visual sesaat.

Modal adalah kasus paling umum. Di dalam komponen Livewire:

Modal konfirmasi dengan Alpine
<div x-data="{ show: false }">
    <button type="button" wire:click="delete" @click="show = true">
        Hapus
    </button>
 
    <div x-show="show" class="fixed inset-0 bg-black/50" @click="show = false"></div>
 
    <div x-show="show" role="dialog">
        <h2>Yakin ingin menghapus?</h2>
        <button type="button" @click="show = false">Batal</button>
        <button type="button" @click="show = false; $wire.deleteConfirmed()">Ya, hapus</button>
    </div>
</div>

Perhatikan campurannya: wire:click untuk aksi server (delete), @click untuk state visual (show). Saat user menekan "Ya, hapus", Alpine menutup modal lalu memanggil $wire.deleteConfirmed() — action Livewire dari dalam ekspresi Alpine.

Objek $wire

$wire adalah jembatan dari Alpine ke komponen Livewire. Dari ekspresi Alpine, $wire memberi akses ke:

  • Method/action: $wire.deleteConfirmed(), $wire.save()
  • Property: $wire.search, $wire.title = 'baru'
  • Entangle (state bersama) — kita bahas di episode 18
Memanggil action via $wire
<button type="button" @click="$wire.refreshStats()">Muat ulang statistik</button>

Ini berguna saat aksi perlu dipicu dari logika Alpine yang kompleks (setelah animasi selesai, setelah kondisi tertentu terpenuhi), bukan langsung dari klik.

Transisi Halus

Alpine menyediakan x-transition untuk animasi masuk/keluar:

Modal dengan transisi
<div x-show="show" x-transition.opacity.duration.200ms>
    <!-- isi modal -->
</div>
Toast notification
<div
    x-show="show"
    x-transition:enter="transition ease-out duration-300"
    x-transition:enter-start="opacity-0 translate-y-2"
    x-transition:enter-end="opacity-100 translate-y-0"
>
    Post berhasil disimpan.
</div>

Animasikan kemunculan dan kehilangan — transisi yang baik menandakan elemen muncul dan menghilang secara konsisten.

Notification Pattern Lengkap

Kombinasi Livewire + Alpine untuk notifikasi setelah aksi server:

app/Livewire/PostEditor.php
use Livewire\Attributes\On;
 
#[On('toast')]
public function toast(string $message)
{
    $this->js("showToast('{$message}')");
}
Script toast di layout/komponen
<script>
    function showToast(message) {
        const el = document.getElementById('toast');
        el.textContent = message;
        el.classList.remove('hidden');
        setTimeout(() => el.classList.add('hidden'), 2500);
    }
</script>

Di sini $this->js() (dibahas di episode 18) menjalankan JavaScript di client setelah aksi server selesai. Event + $wire + $this->js() adalah toolkit lengkap untuk feedback yang halus.

Note

Aturan pemilihan yang harus diingat: Jika state-nya perlu diketahui server → Livewire. Jika hanya memengaruhi tampilan di browser itu sendiri → Alpine. Memindahkan dropdown yang sedang terbuka ke public property Livewire berarti tiap buka-tutup mengirim request — boros dan terasa lambat.

Pitfall Umum

  • State visual di Livewire: dropdown/modal terbuka seharusnya milik Alpine, bukan property Livewire.
  • Lupa @click.outside: dropdown tidak menutup saat klik di luar — UX yang menjengkelkan.
  • Memanggil action via $wire tanpa alasan: jika tombolnya langsung, wire:click lebih ekspresif. $wire untuk kasus yang butuh logika Alpine.
  • Alpine state yang menyimpan data penting: data penting (yang perlu disimpan/dibagikan) tetap di Livewire; Alpine hanya untuk presentasi.
  • Konflik x-data dengan morphing: pastikan x-data berada di elemen yang distabilkan wire:key saat ada di dalam loop.

Penutup

Inti yang harus dibawa pulang:

  • Alpine menangani state visual sesaat (x-data, x-show, @click); Livewire menangani state server.
  • Modal/dropdown = pola x-data + x-show + @click.outside, tanpa request server.
  • $wire menjembatani Alpine ke komponen: panggil action, baca/ubah property.
  • x-transition untuk animasi masuk-keluar yang konsisten.
  • Notifikasi bisa dibangun dengan event + $this->js().

Di episode 16 selanjutnya kita akan membahas loading, polling & offline stateswire:loading dan wire:target untuk spinner/skeleton, wire:poll untuk auto-refresh, serta indikator offline agar aplikasi tidak membisu saat koneksi terputus. Sampai jumpa di episode 16!

Belajar Livewire - Alpine.js Integration | Belajar Livewire