Laravel

Laravel is a powerful and popular PHP framework that simplifies and accelerates web application development. Its elegant syntax, robust features like Eloquent ORM, Blade templating, and built-in security tools help developers create efficient and scalable apps. With strong community support and extensive documentation, Laravel is an ideal choice for both novice and experienced developers

Laravel Blade Components and Slots: A Comprehensive Guide

15 May 2025 | Category:

Blade components and slots are powerful features in Laravel’s templating engine, enabling developers to create reusable, modular, and maintainable UI elements. Components encapsulate HTML, CSS, and logic, while slots provide flexibility for injecting dynamic content into those components. This SEO-friendly, plagiarism-free guide explains Blade components and slots, how to create and use them, and best practices. Based on Laravel 11 (as of May 2025), this tutorial is designed for beginners and intermediate developers.


What are Blade Components and Slots?

Blade Components

A Blade component is a reusable piece of UI (e.g., a button, modal, or alert) defined as a class and a corresponding Blade template. Components combine logic and presentation, making it easy to reuse complex UI elements across your application.

Slots

Slots are placeholders within a component’s template that allow you to inject custom content when using the component. They provide flexibility, enabling components to adapt to different contexts while maintaining a consistent structure.

Key Benefits

  • Reusability: Define UI elements once and use them anywhere.
  • Modularity: Keep templates organized and maintainable.
  • Flexibility: Slots allow customization of component content.
  • Consistency: Ensure uniform design and behavior across views.
  • Encapsulation: Combine logic and markup in a single unit.

Creating a Blade Component

Laravel provides Artisan commands to generate components, or you can create them manually. Components consist of:

  • Class: Handles logic and data (in app/View/Components/).
  • Template: Defines the markup (in resources/views/components/).

Step 1: Generate a Component

Run the Artisan command to create a component:

php artisan make:component Alert

This generates:

  • Class: app/View/Components/Alert.php
  • Template: resources/views/components/alert.blade.php

Step 2: Define the Component

Component Class (Alert.php):

<?php

namespace App\View\Components;

use Illuminate\View\Component;

class Alert extends Component
{
    public $type;
    public $dismissible;

    public function __construct($type = 'info', $dismissible = false)
    {
        $this->type = $type;
        $this->dismissible = $dismissible;
    }

    public function render()
    {
        return view('components.alert');
    }
}
  • Properties: $type and $dismissible are passed as attributes.
  • render(): Points to the component’s Blade template.

Component Template (alert.blade.php):

<div class="alert alert-{{ $type }} {{ $dismissible ? 'alert-dismissible' : '' }}" role="alert">
    {{ $slot }}
    @if($dismissible)
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
    @endif
</div>
  • $slot: Placeholder for content passed between the component’s tags.
  • Dynamic Classes: Uses $type and $dismissible for styling.

Step 3: Use the Component

Use the component in a Blade view with the x- prefix:

<x-alert type="success" :dismissible="true">
    Operation completed successfully!
</x-alert>
  • type=”success”: Sets the alert style (e.g., green for success).
  • :dismissible=”true”: Enables the close button (uses : for PHP expressions).
  • Content: “Operation completed successfully!” is passed to $slot.

Output (assuming Bootstrap CSS):

<div class="alert alert-success alert-dismissible" role="alert">
    Operation completed successfully!
    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>

Working with Slots

Slots allow you to inject custom content into specific parts of a component’s template. Components can have a default slot (unnamed) and named slots for more complex structures.

Default Slot

The default slot ($slot) captures content passed between the component’s opening and closing tags.

Example Template (modal.blade.php):

<div class="modal fade" id="myModal">
    <div class="modal-dialog">
        <div class="modal-content">
            {{ $slot }}
        </div>
    </div>
</div>

Usage:

<x-modal>
    <div class="modal-header">
        <h5>Modal Title</h5>
    </div>
    <div class="modal-body">
        <p>Modal content goes here.</p>
    </div>
</x-modal>
  • The header and body are injected into $slot.

Named Slots

Named slots allow you to define multiple placeholders for specific content.

Component Template (card.blade.php):

<div class="card">
    <div class="card-header">
        {{ $header }}
    </div>
    <div class="card-body">
        {{ $slot }}
    </div>
    <div class="card-footer">
        {{ $footer }}
    </div>
</div>

Usage:

<x-card>
    <x-slot name="header">
        <h5>Card Title</h5>
    </x-slot>
    <p>This is the card body content.</p>
    <x-slot name="footer">
        <button>Save</button>
    </x-slot>
</x-card>
  • <x-slot name="header">: Assigns content to the $header slot.
  • Default content ( <p>) goes to $slot.
  • <x-slot name="footer">: Assigns content to the $footer slot.

Shorthand Syntax:

<x-card>
    @slot('header')
        <h5>Card Title</h5>
    @endslot
    <p>Card body content.</p>
    @slot('footer')
        <button>Save</button>
    @endslot
</x-card>

Conditional Slots

Check if a slot has content using @isset:

<div class="card">
    @isset($header)
        <div class="card-header">{{ $header }}</div>
    @endisset
    <div class="card-body">{{ $slot }}</div>
</div>
  • The header is only rendered if the $header slot is provided.

Passing Data to Components

Components can accept data via attributes, constructor parameters, or slots.

Via Attributes

Pass data as HTML attributes:

<x-alert type="danger" :dismissible="true">
    Error occurred!
</x-alert>
  • type="danger": Static value.
  • :dismissible="true": Dynamic PHP expression.

Via Constructor

The component class constructor defines accepted parameters:

public function __construct($type = 'info', $dismissible = false)
{
    $this->type = $type;
    $this->dismissible = $dismissible;
}

Via Slots

Pass structured content through slots, as shown in the named slots example.

Accessing Attributes in Templates

All attributes are available in the template via $attributes:

<div {{ $attributes->merge(['class' => 'alert alert-' . $type]) }}>
    {{ $slot }}
</div>
  • $attributes->merge(): Combines passed attributes with defaults.

Anonymous Components

Anonymous components are simpler, consisting only of a Blade template without a class. They’re ideal for purely presentational elements.

Create an Anonymous Component

Create a file in resources/views/components/ (e.g., button.blade.php):

<button {{ $attributes->merge(['class' => 'btn btn-' . ($type ?? 'primary')]) }}>
    {{ $slot }}
</button>

Use the Component

<x-button type="success">
    Click Me
</x-button>
  • No class is needed; the template handles everything.
  • Attributes like type are accessed directly.

Advanced Component Features

Component Aliases

Register a shorter alias for components in app/Providers/AppServiceProvider.php:

public function boot()
{
    Blade::component('components.alert', 'alert-box');
}

Use as:

<x-alert-box type="info">Message</x-alert-box>

Dynamic Components

Render components dynamically:

@php
    $componentName = 'alert';
@endphp
<x-dynamic-component :component="$componentName" type="warning">
    Warning message!
</x-dynamic-component>

Component Methods

Add methods to the component class for logic:

public function isDismissible()
{
    return $this->dismissible;
}

Use in the template:

@if($component->isDismissible())
    <button class="btn-close"></button>
@endif

Inline Components

Define a component in a single file without a separate template:

public function render()
{
    return <<<'blade'
        <div class="alert alert-{{ $type }}">
            {{ $slot }}
        </div>
    blade;
}

Best Practices for Blade Components and Slots

  1. Use Components for Reusability: Encapsulate repeated UI elements (e.g., buttons, modals).
  2. Leverage Slots: Use named slots for flexible, complex components.
  3. Keep Components Focused: Each component should have a single responsibility.
  4. Use Anonymous Components for Simplicity: Opt for anonymous components for lightweight UI.
  5. Secure Output: Rely on {{ }} for escaped output; use {!! !!} cautiously.
  6. Merge Attributes: Use $attributes->merge() to combine classes or attributes.
  7. Organize Components: Group related components in subdirectories (e.g., resources/views/components/forms/).
  8. Test Components: Write tests for component logic in tests/.

Example: Real-World Component

Modal Component (modal.blade.php):

<div class="modal fade" id="{{ $id }}" tabindex="-1">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                {{ $header }}
            </div>
            <div class="modal-body">
                {{ $slot }}
            </div>
            <div class="modal-footer">
                {{ $footer }}
            </div>
        </div>
    </div>
</div>

Class (Modal.php):

namespace App\View\Components;

use Illuminate\View\Component;

class Modal extends Component
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

    public function render()
    {
        return view('components.modal');
    }
}

Usage:

<x-modal id="confirmModal">
    <x-slot name="header">
        <h5>Confirm Action</h5>
    </x-slot>
    <p>Are you sure you want to proceed?</p>
    <x-slot name="footer">
        <button class="btn btn-primary" data-bs-dismiss="modal">Cancel</button>
        <button class="btn btn-danger">Confirm</button>
    </x-slot>
</x-modal>

Conclusion

Blade components and slots are essential for building modular, reusable, and maintainable views in Laravel. Components encapsulate UI logic and markup, while slots provide flexibility for injecting custom content. By using class-based or anonymous components, leveraging named slots, and following best practices, you can create clean, consistent, and scalable front-end code.

Next Steps:

  • Create a component: php artisan make:component Alert.
  • Experiment with named slots in a complex component like a modal.
  • Explore Laravel’s official documentation for advanced component features.

For further learning, engage with the Laravel community on platforms like X or dive into the official Laravel documentation. Start building reusable UI with Blade components today!