Seri Belajar Laravel: ← Part 5 — Form & CRUD  |  Part 6 — Layout Blade  |  Part 7 — Authentication →

Kalau kamu lihat file-file view yang kita buat, setiap file mengulang <!DOCTYPE html>, <head>, CSS yang sama. Ini buruk: kalau mau mengubah warna navbar, harus edit semua file satu per satu.

Solusinya: layout Blade. Buat satu file layout induk, semua halaman tinggal "mewarisi" layout tersebut dan hanya mengisi konten yang berbeda.

📋 Progress Belajarmu

① Buat Layout Utama

Buat folder resources/views/layouts/ dan buat file app.blade.php di dalamnya:

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@yield('title', 'Aplikasi Catatan')</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-50 text-gray-800">

    {{-- Navbar --}}
    <nav class="bg-teal-700 text-white px-6 py-4 flex items-center justify-between">
        <a href="/catatan" class="font-bold text-lg">📝 Catatanku</a>
        <a href="/catatan/create"
           class="bg-white text-teal-700 font-semibold px-4 py-2 rounded-lg text-sm hover:bg-gray-100">
            + Catatan Baru
        </a>
    </nav>

    {{-- Flash message --}}
    @if(session('sukses'))
        <div class="max-w-2xl mx-auto mt-4 px-4">
            <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
                ✓ {{ session('sukses') }}
            </div>
        </div>
    @endif

    {{-- Konten halaman --}}
    <main class="max-w-2xl mx-auto px-4 py-8">
        @yield('content')
    </main>

    <footer class="text-center text-gray-400 text-sm py-8">
        Dibuat dengan Laravel ❤️
    </footer>

</body>
</html>

② Refactor View: index.blade.php

Sekarang update semua view untuk menggunakan layout. Ganti seluruh isi catatan/index.blade.php:

@extends('layouts.app')

@section('title', 'Daftar Catatan')

@section('content')
    <div class="flex items-center justify-between mb-6">
        <h1 class="text-2xl font-bold">Daftar Catatan</h1>
        <span class="text-gray-500 text-sm">{{ $catatan->count() }} catatan</span>
    </div>

    @forelse($catatan as $item)
        <div class="bg-white rounded-xl border border-gray-200 p-5 mb-3 hover:shadow-sm transition">
            <div class="flex items-start justify-between">
                <div>
                    <h3 class="font-semibold text-lg">
                        <a href="/catatan/{{ $item->id }}" class="hover:text-teal-600">
                            {{ $item->judul }}
                        </a>
                    </h3>
                    <p class="text-gray-500 text-sm mt-1">{{ Str::limit($item->isi, 80) }}</p>
                </div>
                @if($item->penting)
                    <span class="text-xs bg-red-100 text-red-600 px-2 py-1 rounded-full ml-2">⭐ Penting</span>
                @endif
            </div>
            <div class="flex items-center gap-4 mt-3 pt-3 border-t border-gray-100">
                <span class="text-xs text-gray-400">{{ $item->created_at->diffForHumans() }}</span>
                <a href="/catatan/{{ $item->id }}/edit" class="text-xs text-blue-600 hover:underline">Edit</a>
                <form action="/catatan/{{ $item->id }}" method="POST" class="inline"
                      onsubmit="return confirm('Hapus catatan ini?')">
                    @csrf @method('DELETE')
                    <button class="text-xs text-red-500 hover:underline">Hapus</button>
                </form>
            </div>
        </div>
    @empty
        <div class="text-center py-12 text-gray-400">
            <p class="text-4xl mb-3">📝</p>
            <p>Belum ada catatan. Yuk tambah yang pertama!</p>
        </div>
    @endforelse
@endsection

③ Refactor Form Create & Edit

Karena form create dan edit sangat mirip, buat partial yang bisa dipakai keduanya. Buat resources/views/catatan/_form.blade.php:

<div class="space-y-4">
    <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">Judul</label>
        <input type="text" name="judul"
               value="{{ old('judul', $catatan->judul ?? '') }}"
               class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-teal-500">
        @error('judul')
            <p class="text-red-500 text-sm mt-1">{{ $message }}</p>
        @enderror
    </div>

    <div>
        <label class="block text-sm font-medium text-gray-700 mb-1">Isi Catatan</label>
        <textarea name="isi" rows="6"
                  class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-teal-500"
        >{{ old('isi', $catatan->isi ?? '') }}</textarea>
        @error('isi')
            <p class="text-red-500 text-sm mt-1">{{ $message }}</p>
        @enderror
    </div>

    <label class="flex items-center gap-2 cursor-pointer">
        <input type="checkbox" name="penting" value="1"
               {{ old('penting', $catatan->penting ?? false) ? 'checked' : '' }}
               class="rounded text-teal-600">
        <span class="text-sm text-gray-700">Tandai sebagai penting</span>
    </label>
</div>

Gunakan partial ini di create.blade.php:

@extends('layouts.app')
@section('title', 'Tambah Catatan')
@section('content')
    <h1 class="text-2xl font-bold mb-6">Tambah Catatan Baru</h1>
    <div class="bg-white rounded-xl border border-gray-200 p-6">
        <form action="/catatan" method="POST" class="space-y-4">
            @csrf
            @include('catatan._form')
            <button type="submit"
                    class="bg-teal-600 text-white px-6 py-2 rounded-lg hover:bg-teal-700 font-medium">
                Simpan Catatan
            </button>
        </form>
    </div>
@endsection

Dan di edit.blade.php:

@extends('layouts.app')
@section('title', 'Edit Catatan')
@section('content')
    <h1 class="text-2xl font-bold mb-6">Edit Catatan</h1>
    <div class="bg-white rounded-xl border border-gray-200 p-6">
        <form action="/catatan/{{ $catatan->id }}" method="POST">
            @csrf @method('PUT')
            @include('catatan._form')
            <div class="flex gap-3 mt-4">
                <button type="submit"
                        class="bg-teal-600 text-white px-6 py-2 rounded-lg hover:bg-teal-700 font-medium">
                    Perbarui
                </button>
                <a href="/catatan"
                   class="border border-gray-300 text-gray-600 px-6 py-2 rounded-lg hover:bg-gray-50">
                    Batal
                </a>
            </div>
        </form>
    </div>
@endsection

Ringkasan Directive Blade Layout

DirectiveDipakai diFungsi
@yield('nama')Layout indukTentukan slot yang bisa diisi child
@extends('layouts.app')View childGunakan layout ini sebagai induk
@section('nama') ... @endsectionView childIsi slot yang didefinisikan @yield
@include('partial')View manapunSisipkan file partial
@forelse ... @empty ... @endforelseView manapunLoop dengan fallback kalau kosong

Langkah Selanjutnya

Aplikasi catatan kamu sekarang punya tampilan yang konsisten dan profesional! Di Part 7 — Authentication, kita akan menambahkan sistem login agar hanya user yang login yang bisa mengelola catatannya sendiri.