Home

4 minute read

The Benefits of Blade View Components

Tony Lea

The Benefits of Blade View Components

I've been around the Laravel game for quite some time now, and sometimes it's kind of hard to keep up with all the awesome new features released in this framework. I finally got around to digging into Blade View Components, which allow you to create reusable custom HTML tags. For instance, say that we had a common card element inside our application that looks like this:

<div class="card">
    <h2>Title</h2>
    <p>Description</p>
</div>

Now, instead of duplicating this code whenever we wanted to reuse it, we could create a blade component like so:

php artisan make:component Card

When you run the command, it will create an empty view component located at resources/views/components/card.blade.php. If we put our HTML into that file and want to reference our card element inside a view, we can now use the following HTML tag:

<x-card></x-card>

Pretty cool, right?

When you create a new blade component, it will also create a controller for that component at app/View/Components/Card.php. You can reference the docs to learn more about this, but in our case, we'll be referencing the view component.

Now that you have a general idea of what blade view components are, you can decide if they're right for you by checking out the top benefits of using blade view components.

Slots

If you're familiar with VueJS, this will be simple to understand. Using slots allow us to define slots in our component where we want to add more HTML. We can do this by adding {{ $slot }} to our component, like so:

<div class="card">
    <h2>{{ $slot }}</h2>
    <p>Description</p>
</div>

We can now pass data to that component inside our custom tag:

<x-card>Blade Rocks</x-card>

When that component is rendered it will output the following HTML:

<div class="card">
    <h2>Blade Rocks</h2>
    <p>Description</p>
</div>

Nothing too difficult. You with me?

In addition to slots, you can also use named slots to add HTML in different places of your component:

<div class="card">
    <h2>{{ $slot }}</h2>
    <p>{{ $description }}</p>
</div>

We can now pass data to multiple slots inside of our component:

<x-card>
    Blade Rocks
    <x-slot name="description">Slots for the win</x-slot>
</x-card>

Now, our rendered HTML output would look like the following:

<div class="card">
    <h2>Blade Rocks</h2>
    <p>Slots for the win</p>
</div>

And that's a basic example of using slots and named slots.

Props

Props allow you to pass data as properties to the component, like so:

@props(['src'])

<div class="card">
    <img src="{{ $src }}">
    <h2>{{ $slot }}</h2>
    <p>{{ $description }}</p>
</div>

We could then pass a prop to our component:

<x-card src="img.png">
    Blade Rocks
    <x-slot name="description">Slots for the win</x-slot>
</x-card>

The value passed in as src will get forwarded to the src attribute of the image in our card element.

Great! Now what if we had a variable that we needed to pass to our Blade View Component? Simple enough, we can prepend the attribute with a semicolon, like so:

<x-card :src="$image">
    Blade Rocks
    <x-slot name="description">Slots for the win</x-slot>
</x-card>

Quick note: if you get an error that the prop variable does not exist, you will need to remove the component controller. By doing that, we are creating an anonymous component. Read more about anonymous components.

Attribute Forwarding

With attribute forwarding you can forward all attributes from the HTML tag to the component:

<div {{ $attributes }}>
    <h2>{{ $slot }}</h2>
    <p>{{ $description }}</p>
</div>

Now, if we were to call the component we can add some class attributes and forward them to the component:

<x-card class="card bg-white">
    Blade Rocks
    <x-slot name="description">Slots for the win</x-slot>
</x-card>

And the rendered HTML will be the following:

<div class="card bg-white">
    <h2>Blade Rocks</h2>
    <p>Slots for the win</p>
</div>

Hope you are with me so far. Ok, now what if our component already had a class and we want to add more classes. Simple enough, we can use the attribute merge function for that. We can change our component to the following:

<div {{ $attributes->merge(['class' => 'card']) }}>
    <h2>{{ $slot }}</h2>
    <p>{{ $description }}</p>
</div>

And now, we can display our custom HTML card element like so:

<x-card class="bg-white">
    Blade Rocks
    <x-slot name="description">Slots for the win</x-slot>
</x-card>

And the attributes will be merged into the final output:

<div class="card bg-white">
    <h2>Blade Rocks</h2>
    <p>Slots for the win</p>
</div>

There's a bunch of other cool things you can do with attributes, be sure to check out the Laravel docs on Blade View Components to learn more about this.

Conclusion

If you are also familiar with Laravel Livewire, you can take advantage of even more cool features with Blade and Livewire Components.

Thanks for joining me down this road on learning Blade View Components. The next time you're crafting another Laravel application, be sure to reach for these Blade View Components to make your views more efficient and easier to read.