Hace poco, por exigencias del guión, he descubierto los componentes y slots en Laravel. Y tengo que decir que me han resultado una herramienta muy útil para maquetar partes de una web que repiten la misma estructura pero con cambios pequeños.
Concretamente tenía una cabecera con 4 partes: migas de pan, título principal, subtítulo y un botón; pero según la página no había botón o no había migas de pan, o sólo había migas de pan y título principal.
Andaba discurriendo cómo organizar esto, si a tráves de @include y pasándole parámetros o @yield o cómo, y me encontré con la opción de @component y @slot en la documentación de Laravel:
https://laravel.com/docs/5.8/blade#components-and-slots
Conocía el concepto de los slots de Vue pero no sabía que estaban también disponibles en Laravel.
Creamos un componente como una vista más, es un archivo .blade.php como el resto.
Dentro tenemos código html a modo de plantilla para después hacer una llamada @component(‘ruta.al.componente’) y funcionaría igual que si hacemos un @include(‘ruta.a.la.vista’)
<header class="row pagina__cabecera">
<div class="col-md-9 cabecera__contenido">
<nav class="cabecera__migas_de_pan" aria-label="breadcrumb">
<ol class="breadcrumb breadcrumb-style1">
{{$cabecera_migas_de_pan}}
</ol>
</nav>
<h1 class="cabecera__titulo">{{$cabecera_titulo}}</h1>
<p class="cabecera__subtitulo">{{$cabecera_subtitulo}}</p>
</div>
<div class="col-md-3 cabecera__acciones">
{{$cabecera_acciones}}
</div>
</header>
Dentro de nuestro componente podemos interpolar variables mediante dobles llaves. Hasta aquí poco o nada distinto de utilizar un @include
La diferencia reside en que mientras para un @include(‘…’) sólo le pasamos la ruta, para un @component(‘…’) le pasamos la ruta y tenemos directiva de cierre @endcomponent . Entre medias podemos usar @slot(‘variable’) para dar contenido a esas variables interpoladas en la plantilla de nuestro componente:
@section('cabecera')
@component('distribucion.cabecera.contenedor')
@slot('cabecera_titulo')
Issues
@endslot
@slot('cabecera_subtitulo')
From this screen you can check the activities generated by the system and also you can register others
@endslot
@slot('cabecera_acciones')
<button class="btn btn-sm btn-primary">
<i data-feather="plus-circle" class="wd-10"></i> Añadir nuevo
</button>
@endslot
@endcomponent
@endsection
En mi caso, encerré cada @slot dentro de un @if correspondiente para que si no recibe la variable no se pinte y así, manteniendo la estructura, cargar el componente con los elementos que toquen.
<header class="row pagina__cabecera">
<div class="col-md-9 cabecera__contenido">
@if(isset($cabecera_migas_de_pan))
<nav class="cabecera__migas_de_pan" aria-label="breadcrumb">
<ol class="breadcrumb breadcrumb-style1">
{{$cabecera_migas_de_pan}}
</ol>
</nav>
@endif
@if(isset($cabecera_titulo))
<h1 class="cabecera__titulo">{{$cabecera_titulo}}</h1>
@endif
@if(isset($cabecera_subtitulo))
<p class="cabecera__subtitulo">{{$cabecera_subtitulo}}</p>
@endif
</div>
@if(isset($cabecera_acciones))
<div class="col-md-3 cabecera__acciones">
{{$cabecera_acciones}}
</div>
@endif
</header>
Aunque pueda ser algo más extenso lo veo más cómodo que cargar variables como parámetros en un @include y dentro de los @slot puedo colocar código html tabulado y organizado para que sea más legible.
@section('cabecera')
@component('distribucion.cabecera.contenedor')
@slot('cabecera_titulo')
Issues
@endslot
@slot('cabecera_subtitulo')
From this screen you can check the activities generated
by the system and also you can register others
@endslot
@slot('cabecera_acciones')
<button class="btn btn-sm btn-primary">
<i data-feather="plus-circle" class="wd-10"></i> Añadir nuevo
</button>
@endslot
@endcomponent
@endsection
En la documentación de Laravel se explican algunas posibilidades más como que también se puede pasar parámetros al componente
@component('alert', ['foo' => 'bar'])
O incluso crear una directiva propia para llamarlo
Blade::component('components.alert', 'alert');
@alert
You are not allowed to access this resource!
@endalert
En este caso yo seguiría la buena práctica de los web components y nombraría a directiva con al menos 2 palabras (p.e. componente-alerta).