Layout Blade + Componente-bueno componente in

 

Layout Blade + Componente

Vamos a crear un ejemplo completo con:

  1. Un layout en Blade (el cascarón de la página).

  2. Un componente chiquito que se usa dentro del layout.


Archivo 1: El layout

resources/views/layouts/app.blade.php

blade
<!DOCTYPE html>
<html>
    <head>
        <title>@yield('title', 'Mi App')</title>
    </head>
    <body>
        <header>Mi sitio web</header>

        <main>
            @yield('content')
        </main>

        <footer>© 2026</footer>
    </body>
</html>

Este es un layout clásico de Blade. Usa @yield, no $slot. No es un componente. Es una plantilla normal que otras vistas van a extender.

  • @yield('title') → hueco para el título.

  • @yield('content') → hueco para el contenido.


Archivo 2: El componente

resources/views/components/alerta.blade.php

blade
@props(['tipo' => 'info'])

<div class="alerta alerta-{{ $tipo }}">
    {{ $slot }}
</div>

Este sí es un componente. Tiene:

  • @props → recibe tipo.

  • $slot → recibe el texto.


Archivo 3: La vista que usa el layout y el componente

resources/views/home.blade.php

blade
@extends('layouts.app')

@section('title', 'Lista de tareas')

@section('content')
    <h1>¡Bienvenido!</h1>

    <x-alerta tipo="exito">
        Todo salió bien
    </x-alerta>

    <ul>
        <li>Tarea 1</li>
        <li>Tarea 2</li>
    </ul>
@endsection

Aquí pasa algo importante:

  • @extends('layouts.app') → usa el layout clásico.

  • @section('title', ...) → llena el @yield('title') del layout.

  • @section('content') ... @endsection → llena el @yield('content') del layout.

  • Dentro de @section('content'), se usa <x-alerta> → ahí entra el componente.


¿Qué pasa paso a paso?

Paso 1: Laravel abre home.blade.php y ve @extends('layouts.app'). Entonces carga layouts/app.blade.php.

Paso 2: Laravel busca @yield('title') y lo reemplaza con "Lista de tareas".

Paso 3: Laravel busca @yield('content') y lo reemplaza con todo el contenido del @section('content').

Paso 4: Pero antes de meterlo, procesa el <x-alerta> que hay adentro.

Abre alerta.blade.php:

  • $tipo = "exito"

  • $slot = "Todo salió bien"

Produce:

html
<div class="alerta alerta-exito">
    Todo salió bien
</div>

Paso 5: Ese HTML reemplaza al <x-alerta> dentro del contenido.

Paso 6: El contenido final del @yield('content') queda así:

html
<h1>¡Bienvenido!</h1>

<div class="alerta alerta-exito">
    Todo salió bien
</div>

<ul>
    <li>Tarea 1</li>
    <li>Tarea 2</li>
</ul>

Paso 7: Laravel lo mete en el layout, dentro de <main>.


HTML final

html
<!DOCTYPE html>
<html>
    <head>
        <title>Lista de tareas</title>
    </head>
    <body>
        <header>Mi sitio web</header>

        <main>
            <h1>¡Bienvenido!</h1>

            <div class="alerta alerta-exito">
                Todo salió bien
            </div>

            <ul>
                <li>Tarea 1</li>
                <li>Tarea 2</li>
            </ul>
        </main>

        <footer>© 2026</footer>
    </body>
</html>

La clave: dos mecanismos distintos trabajando juntos

MecanismoArchivoCómo funciona
Layout clásicolayouts/app.blade.phpUsa @yield para los huecos
Componentecomponents/alerta.blade.phpUsa $slot para el contenido

Son dos cosas diferentes:

  • @yield → hueco de un layout clásico (se llena con @section).

  • $slot → hueco de un componente (se llena con lo que va entre <x-alerta> y </x-alerta>).

En este ejemplo, ambos conviven:

  • El layout usa @yield.

  • El componente usa $slot.

  • La vista home.blade.php llena el @yield con @section, y dentro de ese @section usa <x-alerta> para llenar el $slot.


Diferencia con el ejemplo anterior

En el ejemplo anterior que viste, el layout era un componente (<x-layout>) y usaba $slot.

Aquí el layout es clásico (@extends + @yield) y el componente (<x-alerta>) usa $slot.

Ambos enfoques son válidos:

EnfoqueLayoutContenido
Componentes<x-layout> con $slot<x-alerta> con $slot
Clásico + componentes@extends + @yield<x-alerta> con $slot

Puedes mezclarlos. No hay problema.


Resumen

  • Layout clásico → layouts/app.blade.php con @yield.

  • Vista que lo usa → home.blade.php con @extends y @section.

  • Componente → components/alerta.blade.php con @props y $slot.

  • Uso del componente → <x-alerta>...</x-alerta> dentro del @section.

  • $slot → recibe el contenido que va entre <x-alerta> y </x-alerta>.

  • @yield → recibe el contenido de los @section de la vista.

Cada uno tiene su hueco, y Laravel los une en el HTML final.


Cómo funciona el $slot y cómo meter datos a un componente

1. Qué es el $slot

El $slot es una variable especial que Laravel pone a tu disposición dentro de cualquier componente Blade. Contiene todo el contenido HTML/texto que escribiste entre las etiquetas de apertura y cierre del componente.

blade
<x-alerta tipo="exito">
    Todo salió bien      <-- ESTO es el $slot
</x-alerta>

Dentro de alerta.blade.php, {{ $slot }} se reemplaza por "Todo salió bien".

Regla mental: $slot = el "relleno" que va dentro del componente. Es el equivalente a un @yield('content') pero para componentes.


2. Cómo meter datos al componente: dos vías

Hay dos formas distintas de pasar información a un componente, y conviene no confundirlas:

VíaCómo se escribeCómo se lee dentroPara qué sirve
Atributos<x-alerta tipo="exito">@props(['tipo' => 'info']) → $tipoDatos de configuración (tipo, color, id, etc.)
SlotContenido entre etiquetas{{ $slot }}Contenido principal (texto, HTML, otros componentes)

En el ejemplo:

blade
<x-alerta tipo="exito">
    Todo salió bien
</x-alerta>
  • tipo="exito" → llega como atributo/prop → se usa en alerta-{{ $tipo }}

  • Todo salió bien → llega como slot → se pinta con {{ $slot }}


3. @props: declarar qué atributos acepta el componente

blade
@props(['tipo' => 'info'])

Esto hace tres cosas:

  1. Declara que el componente acepta un atributo llamado tipo.

  2. Define un valor por defecto ('info') si no se lo pasan.

  3. Extrae ese atributo de la bolsa de atributos, para que no se imprima como atributo HTML suelto.

Si no declaras @props, cualquier atributo que pases se renderiza tal cual en el HTML (comportamiento de "attribute bag"), lo cual puede no ser lo que quieres.


4. Variantes útiles

a) Valor por defecto si no se pasa el prop

blade
@props(['tipo' => 'info'])
  • <x-alerta>...</x-alerta> → $tipo = 'info'

  • <x-alerta tipo="exito">...</x-alerta> → $tipo = 'exito'

b) Slots con nombre (varios huecos)

Si quieres más de un hueco, además del principal:

blade
<!-- components/card.blade.php -->
@props(['titulo'])

<div class="card">
    <h2>{{ $titulo }}</h2>
    <div>{{ $slot }}</div>
    <footer>{{ $footer }}</footer>
</div>

Uso:

blade
<x-card titulo="Mi tarjeta">
    Contenido principal (va al $slot)
    <x-slot:footer>
        Pie de la tarjeta
    </x-slot:footer>
</x-card>

Aquí:

  • titulo → prop

  • contenido entre <x-card> y <x-slot:footer> → $slot

  • contenido dentro de <x-slot:footer> → $footer

c) Atributos extra ($attributes)

Todo lo que no declares en @props cae en $attributes, que puedes volcar en el HTML:

blade
@props(['tipo' => 'info'])

<div {{ $attributes->merge(['class' => "alerta alerta-$tipo"]) }}>
    {{ $slot }}
</div>

Uso:

blade
<x-alerta tipo="exito" id="msg-1" class="mt-4">
    Todo salió bien
</x-alerta>

Resultado:

html
<div id="msg-1" class="alerta alerta-exito mt-4">
    Todo salió bien
</div>

5. Resumen visual del flujo

text
<x-alerta tipo="exito">        <-- atributo  --> $tipo (vía @props)
    Todo salió bien            <-- contenido --> $slot (vía {{ $slot }})
</x-alerta>

Dentro del componente:

blade
@props(['tipo' => 'info'])     {{-- recibe atributos --}}

<div class="alerta alerta-{{ $tipo }}">
    {{ $slot }}                {{-- recibe el contenido --}}
</div>

6. La clave para no confundirte

  • $slot = "lo que va dentro de las etiquetas del componente". Es contenido.

  • @props / $tipo = "lo que va en los atributos de la etiqueta del componente". Es configuración.

Son dos canales distintos y complementarios: uno para qué se muestra (slot) y otro para cómo se muestra (props).

Comentarios

Entradas más populares de este blog

02 -Rutas en Laravel

01-04-convencion nombres

1-4-Evolución en PHP Puro-Credenciales en Body/Query String: