Anonymous Blade Components

Saurabh Mahajan
4 min readJan 22, 2021

--

Blade Components have been around Laravel since long, however they gain immense popularity with the release of Jetstream. Jetstream uses Blade Components to keep all the Views consistent and helps to avoid duplicating any Html and thereby keeping the things DRY.

Besides Anonymous Components there are Class Based Components as well. However, in most of the cases Anonymous Components are well suited for most Use Cases. In order to define an Anonymous Component, you only need to create a New Blade File in /resouces/views/componentsDirectory.

If we put a card.blade.php at above location with following content:

<div class="card">
<div class="card-body">
This is some text within a card body.
</div>
</div>

Now we have a Anonymous Card Component which we can use anywhere to render a Card . In order to render a Component you need to use the keyword x- followed by the kebab case name of the component. So we can use this Card Component like below:

<x-card></x-card>

Now we can use this multiples times in a Single Blade File and make sure our Card is consistent through out application. And if we need to make any changes we only need to do in 1 file only.

At this stage our Component is not much useful as it only provides Static Content. Lets make it more useful by introducing Slots. So anything passed between the Opening and Closing Tag is available inside the Component as $slot Variable. So we are going to change our Card Component like below:

<div class=”card”>
<div class=”card-body”>
{{$slot}}
</div>
</div>

And now we can use the Card Component like below and it will give the same output as before.

<x-card>This is some text within a card body.</x-card>

Now lets say we want to give a Header to our Card Component. Our Card Component will change like below

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

However, we want to make sure that Card Header can also be customized. In order to make this work we will need multiple Slots. So we will call this $title and change our Card Component as

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

Now, we need to pass multiple Slots, we can do so using x-slot and we need to give it a name property which should match the slot name, which in this case is title. So now we can call our Card Component as

<x-card>
<x-slot name="title">Card Header</x-slot>
This is some text within a card body.
</x-card>

Laravel is smart enough to find the values of $slot and $title from above and pass it to our Component.

Now suppose we are using this Component at multiple places. However, at 1 of the place we need to pass it a class of w-25 so that it takes 25% of the width. We can do so with the help of attributes. We can call our Component like below:

<x-card class="w-25" id="some-id-for-card">
<x-slot name="title">Title</x-slot>
This is some text within a card body.
</x-card>

We are passing class and id as the extra arguments. And we can then change our Component to merge any incoming arguments with the already available ones.

<div {{$attributes->merge(['class' => 'card']) }}>
<div class="card-header">
{{ $title }}
</div>
<div class="card-body">
{{$slot}}
</div>
</div>

The Resulting output would be like below:

<div class="card w-25" id="some-id-for-card">

We see that id attribute is added as it was passed. However, the Card has both w-25 and card class. All the incoming classes were merged with the already available ones and nothing was overwritten. This is a very useful feature where you can pass any additional arguments to your Component.

Let us change our Card Component to accept a Footer Text. We can pass the Footer Text in the same way as we have passed id and class. However, then it will also be rendered at the root div as it will be part of the $attributes. To avoid this, we can define Footer Text as props. Anything defined as props is not available in $attributes. So we can change our Component as

@props(['footer']);<div {{$attributes->merge(['class' => 'card']) }}>
<div class="card-header">
{{ $title }}
</div>
<div class="card-body">
{{$slot}}
</div>
<div class="card-footer text-muted">
{{$footer}}
</div>
</div>

This way we can use the $footer as a variable inside our Component and it will no longer be available as$attributes .

We can also define a Default Value of our props within our Component in case a value it is not passed. We just need to change it to a key-value pair.

@props([‘footer’ => ‘Default Value’]);

We can call our Card Component like below:

<x-card class="w-25" id="some-id-for-card" footer="Footer Text">
<x-slot name="title">Title</x-slot>
This is some text within a card body.
</x-card>

In case the footer text to be passed is present in PHP Variable, you must use the : as a prefix like below

<x-card class="w-25" id="some-id-for-card" :footer="$footer">

This is probably everything you need to know in order to use Anonymous Blade Components. They are really helpful in order to keep your Blade Code tidy, clean and maintainable. If you want to learn more about them then you should install Jetstream Livewire Stack and see various Components available and how they are being used.

--

--

Saurabh Mahajan
Saurabh Mahajan

Responses (1)