Beetje Coderen

Les 3 · Module 1 · Laravel-basis

Blade-templates en componenten

Bouw de layout van de kassa met Blade: echo's, @if en @foreach, een gedeelde layout met componenten en slots, en herbruikbare formuliervelden.

⏱ 75–90 minuten leestijd + oefenen

Illustratie: een documentsjabloon en een browservenster, een template dat een webpagina wordt

🎯 Na deze les kun je

  • Blade-directives voor voorwaarden en lussen gebruiken
  • een layout maken als component met slots
  • anonieme en klasse-componenten met props schrijven
  • uitleggen wanneer {!! !!} gevaarlijk is

Elke pagina van de kassa heeft dezelfde kop, hetzelfde menu en dezelfde voet. Kopiëren en plakken werkt tot je het menu wilt aanpassen. Blade is de template-taal van Laravel: gewone HTML met een paar @-directives en componenten om stukken te hergebruiken.

Echo's en directives

<p>Hallo {{ $naam }}</p>                   {{-- ge-escapet --}}
<p>{{ $omschrijving ?? 'Geen omschrijving' }}</p>

@if ($regels->isEmpty())
  <p>De bon is leeg.</p>
@elseif ($regels->count() > 10)
  <p>Grote bestelling!</p>
@endif

@foreach ($regels as $regel)
  <li @class(['duur' => $regel['prijs'] > 5])>{{ $regel['naam'] }}</li>
@endforeach

@forelse ($producten as $p)
  <li>{{ $p['naam'] }}</li>
@empty
  <li>Nog geen producten.</li>
@endforelse

In een @foreach heb je $loop: $loop->iteration (vanaf 1), $loop->first, $loop->last, $loop->count. {{-- … --}} is commentaar dat niet in de HTML komt.

Voorspel eerst: $naam is <b>Sam</b>. Wat zie je bij {{ $naam }} en wat bij {!! $naam !!}?

Uitkomst

{{ $naam }} toont letterlijk <b>Sam</b> (de tekens zijn ge-escapet). {!! $naam !!} toont Sam vetgedrukt: de HTML wordt uitgevoerd. Komt $naam van een gebruiker, dan is {!! !!} een XSS-lek. Gebruik het alleen voor HTML die je zelf maakt.

Een layout als component

Maak resources/views/components/layout.blade.php:

<!doctype html>
<html lang="nl">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>{{ $titel ?? 'Kassa' }} · kassa</title>
  @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
  <nav>
    <a href="{{ route('kassa.index') }}">Kassa</a>
    <a href="{{ route('producten.index') }}">Producten</a>
  </nav>
  <main>{{ $slot }}</main>
</body>
</html>

Een pagina gebruikt hem zo:

<x-layout titel="Bon">
  <h1>Bon</h1>
  ...
</x-layout>

Alles tussen <x-layout> en </x-layout> komt in $slot. Een attribuut als titel="Bon" wordt de variabele $titel. @vite laadt CSS en JavaScript via Vite (npm install && npm run dev); zonder Node kun je ook gewoon <link rel="stylesheet" href="{{ asset('css/kassa.css') }}"> gebruiken met een bestand in public/css/.

Benoemde slots

{{-- components/kaart.blade.php --}}
<section class="kaart">
  <header>{{ $kop }}</header>
  {{ $slot }}
  @isset($voet)<footer>{{ $voet }}</footer>@endisset
</section>
<x-kaart>
  <x-slot:kop>Totaal vandaag</x-slot:kop>
  <p>€ 312,40</p>
  <x-slot:voet>Bijgewerkt om 15:00</x-slot:voet>
</x-kaart>

Componenten met props

Een formulierveld komt overal terug. resources/views/components/veld.blade.php:

@props(['naam', 'label', 'type' => 'text'])
<label>
  {{ $label }}
  <input type="{{ $type }}" name="{{ $naam }}" value="{{ old($naam) }}" {{ $attributes }}>
  @error($naam)<span class="fout">{{ $message }}</span>@enderror
</label>
<x-veld naam="prijs" label="Prijs" inputmode="decimal" required />

@props noemt de verwachte eigenschappen met standaardwaarden; alles wat overblijft (inputmode, required) staat in $attributes. old() en @error gebruik je in les 5.

Wil je logica in een component, maak dan een klasse: php artisan make:component Bedrag geeft app/View/Components/Bedrag.php met een render()-methode.

Typische fouten

  • Undefined variable $titel: geef een standaard met ?? of zet hem in @props.
  • Component niet gevonden: het bestand moet in resources/views/components/ staan; <x-formulier.veld> zoekt components/formulier/veld.blade.php.
  • Oude weergave na wijziging: Blade cachet gecompileerde views; php artisan view:clear.

Oefenen

  1. Maak de component layout en laat alle bestaande views hem gebruiken.
  2. Maak een component <x-bedrag :waarde="2.8" /> die € 2,80 toont.
  3. Toon de productlijst met @forelse en markeer producten boven € 4 met @class.
  4. Maak de component kaart met een benoemd slot kop en gebruik hem op de startpagina.
Modelantwoord oefening 1

Elke view begint met <x-layout titel="…"> en eindigt met </x-layout>. Er staat geen <html> of <head> meer in.

Modelantwoord oefening 2
{{-- components/bedrag.blade.php --}}
@props(['waarde'])
<span class="bedrag">€ {{ number_format($waarde, 2, ',', '.') }}</span>

De dubbele punt in :waarde="2.8" betekent: dit is een PHP-expressie, geen tekst.

Modelantwoord oefening 3
@forelse ($producten as $p)
  <li @class(['duur' => $p['prijs'] > 4])>{{ $p['naam'] }} <x-bedrag :waarde="$p['prijs']" /></li>
@empty
  <li>Nog geen producten.</li>
@endforelse
Modelantwoord oefening 4

Zie het voorbeeld bij Benoemde slots. Zonder voet laat @isset de footer weg.

Lokaal oefenen

Geen live lab. Bekijk de bron van je pagina (Ctrl+U) om te zien welke HTML Blade maakt.

Samenvatting

  • {{ }} escapet, {!! !!} niet; @if, @foreach, @forelse, @class sturen.
  • Een layout is een component met $slot; benoemde slots en props maken componenten flexibel.
  • Volgende les: wat Laravel doet tussen verzoek en antwoord.

📝 Quiz: Blade-templates en componenten

5 vragen · 70% nodig om te slagen

1. Wat doet {!! $x !!}?
2. Waar komt de inhoud tussen <x-layout> en </x-layout> terecht?
3. Wat staat er in $attributes van een component?
4. Waar zoekt Laravel <x-formulier.veld>?
5. Wat toont @forelse … @empty als de lijst leeg is?