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
| Directive | Dipakai di | Fungsi |
|---|---|---|
@yield('nama') | Layout induk | Tentukan slot yang bisa diisi child |
@extends('layouts.app') | View child | Gunakan layout ini sebagai induk |
@section('nama') ... @endsection | View child | Isi slot yang didefinisikan @yield |
@include('partial') | View manapun | Sisipkan file partial |
@forelse ... @empty ... @endforelse | View manapun | Loop 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.
Komentar 0