Tutorial Laravel 12 Livewire dan Tailwind CSS #11 Index Livewire Blade View

Pelajari cara membangun aplikasi web modern dengan Laravel 12, Livewire, dan Tailwind CSS. Tutorial ini membahas langkah demi langkah mulai dari instalasi hingga implementasi fitur interaktif tanpa JavaScript. Cocok untuk pemula maupun developer yang ingin meningkatkan skill dalam membangun UI dinamis dan reaktif dengan Livewire serta styling cepat menggunakan Tailwind CSS.

✅ Telah dilihat 526 kali

Rating: 5.00 ⭐

... 18 July 2025, 15:31

Index Livewire Blade View

Silakan teman-teman buka file dengan nama index.blade.php yang terletak didalam folder:

resources/views/livewire/catatan/

Kemudian ubah menjadi seperti berikut ini:

<div class="relative mb-6 w-full">
    <flux:heading size="xl" level="1">{{ __('Catatan') }}</flux:heading>
    <flux:subheading size="lg" class="mb-6">{{ __('Manage your Catatan') }}</flux:subheading>
    <flux:separator variant="subtle" />

    <flux:modal.trigger name="create-catatan">
        <flux:button class="mt-3">Create Catatan</flux:button>
    </flux:modal.trigger>

    @if (session()->has('success'))
    <div
        x-data="{ show: true }"
        x-show="show"
        x-init="setTimeout(() => { show = false }, 3000)"
        class="fixed top-5 right-5 bg-green-600 text-white text-sm p-4 rounded-lg shadow-lg z-50"
        role="alert">
        <p>{{ session('success') }}</p>
    </div>
    @endif

    <livewire:catatan.create />
    <livewire:catatan.edit />
    
    <div class="mt-8 overflow-x-auto">
        <table class="min-w-full divide-y divide-gray-200 rounded-lg shadow-md overflow-hidden">
            <thead class="bg-gray-50 text-gray-700 text-sm uppercase tracking-wider">
                <tr>
                    <th class="px-6 py-3 text-left">#</th>
                    <th class="px-6 py-3 text-left">Judul</th>
                    <th class="px-6 py-3 text-left">Isi</th>
                    <th class="px-6 py-3 text-left">Dibuat</th>
                    <th class="px-6 py-3 text-center">Aksi</th>
                </tr>
            </thead>
            <tbody class="bg-white divide-y divide-gray-100">
                @forelse ($catatans as $index => $catatan)
                <tr>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700">{{ $catatans->firstItem() + $index }}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 flex items-center space-x-3">
                        <img class="w-8 h-8 rounded-full object-cover" src="https://ui-avatars.com/api/?name={{ urlencode($catatan->judul) }}" alt="Avatar">
                        <span>{{ $catatan->judul }}</span>
                    </td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">{{ \Illuminate\Support\Str::limit($catatan->isi, 50) }}</td>
                    <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-400">{{ $catatan->created_at->diffForHumans() }}</td>
                    <td class="px-6 py-4 text-center space-x-2">
                        <flux:button size="sm" variant="primary" wire:click="edit({{ $catatan->id }})">Edit</flux:button>
                        <flux:button size="sm" variant="danger" wire:click="delete({{ $catatan->id }})">Hapus</flux:button>
                    </td>
                </tr>
                @empty
                <tr>
                    <td colspan="6" class="px-6 py-4 text-center text-gray-500">Belum ada catatan.</td>
                </tr>
                @endforelse
            </tbody>
        </table>

        <div class="mt-4">
            {{ $catatans->links() }}
        </div>

        <flux:modal name="delete-catatan" class="min-w-[22rem]">
            <div class="space-y-6">
                <div>
                    <flux:heading size="lg">Delete catatan?</flux:heading>

                    <flux:text class="mt-2">
                        <p>You're about to delete this catatan.</p>
                        <p>This action cannot be reversed.</p>
                    </flux:text>
                </div>

                <div class="flex gap-2">
                    <flux:spacer />

                    <flux:modal.close>
                        <flux:button variant="ghost">Cancel</flux:button>
                    </flux:modal.close>

                    <flux:button type="submit" variant="danger" wire:click="deleteCatatan">Delete catatan</flux:button>
                </div>
            </div>
        </flux:modal>
    </div>
</div>

Struktur Halaman

<div class="relative mb-6 w-full">
    ...
</div>

Kita mulai dengan div utama sebagai pembungkus layout agar semuanya terlihat rapi. Class Tailwind CSS seperti mb-6w-full, dan relative digunakan untuk styling dasar.


Judul Halaman dan Subjudul

<flux:heading size="xl">{{ __('Catatan') }}</flux:heading>
<flux:subheading size="lg">{{ __('Manage your Catatan') }}</flux:subheading>
<flux:separator variant="subtle" />

Ini adalah bagian header halaman. Kita menggunakan komponen dari Flux UI untuk membuat tampilan lebih modern dan konsisten.


Tombol Buat Catatan

<flux:modal.trigger name="create-catatan">
    <flux:button class="mt-3">Create Catatan</flux:button>
</flux:modal.trigger>

Ketika tombol ini diklik, modal create-catatan akan terbuka. Ini memicu komponen Livewire catatan.create.


Notifikasi Sukses

@if (session()->has('success'))
    <div x-data="{ show: true }" ...>{{ session('success') }}</div>
@endif

Kalau ada session flash dengan nama success, maka akan tampil notifikasi hijau di pojok kanan atas dan otomatis hilang setelah 3 detik. Ini memanfaatkan Alpine.js (x-datax-show) untuk efek reaktif.


Panggil Komponen Create & Edit

<livewire:catatan.create />
<livewire:catatan.edit />

Ini memanggil dua komponen anak, satu untuk membuat catatan (Create.php) dan satu untuk mengedit (Edit.php). Mereka masing-masing punya modal sendiri yang akan muncul saat dibutuhkan.

Tabel Daftar Catatan

<table> ... </table>

Bagian inti halaman ini adalah tabel yang menampilkan seluruh data catatan:

  • Nomor urut dihitung dengan $catatans->firstItem() + $index
  • Judul ditampilkan bersama avatar dari ui-avatars.com
  • Isi dipotong pakai Str::limit(...)
  • Tanggal dibuat diformat diffForHumans() biar lebih natural
  • Aksi terdiri dari tombol Edit dan Hapus

Pagination

{{ $catatans->links() }}

Untuk navigasi halaman kalau data catatan banyak, Laravel sudah menyiapkan pagination otomatis.


Modal Konfirmasi Hapus

<flux:modal name="delete-catatan">
    ...
</flux:modal>

Ketika klik tombol "Hapus", kita bisa tampilkan modal ini untuk memastikan user tidak salah klik. Ini adalah UX yang baik, karena mencegah aksi yang tidak bisa dibatalkan.


Kesimpulan

File index.blade.php ini adalah tulang punggung tampilan daftar catatan:

  • Terstruktur rapi dengan komponen Flux UI
  • Menggunakan modal untuk interaksi (Create/Edit/Delete)
  • Sudah responsif dan user-friendly
  • Dihubungkan langsung dengan Livewire Class yang menangani logic

Kalau dianalogikan, ini seperti ruang kerja utama tempat kita melihat semua catatan kita, dan bisa langsung melakukan aksi tanpa pindah halaman. Dengan Livewire, semuanya terjadi dinamis dan cepat, tanpa reload halaman penuh.

🔥 Flash Sale


📜 Table Of Contents


📌 Daftar Episode


Daftar eBook