Laravel Blade - Advantage of @slot/@component vs @include?
Asked Answered
F

5

64

Laravel 5.4 Blade introduced the concept of components & slots - but I can't see what they add over the traditional @include. As I understand, with component/slots, you do:

In template component-tpl.blade.php:

<div class='container'>
  <h1>{{$slot1}}</h1>
  <h2>{{$slot2}}</h2>
</div>

Using slots in page template, you do:

@component('component-tpl')
  @slot('slot1')
    The content of Slot 1
  @endslot
  @slot('slot2')
    The content of Slot 2
  @endslot
@endcomponent

What functionality does that provide over the older:

@include('component-tpl',['slot1'=>'The content of Slot 1',
'slot2'=>"The content of Slot 2"])

using the exact same 'component-tpl.blade.php' Blade template?

What am I missing? Thanks for any insights.

Chris

Fredela answered 27/5, 2017 at 2:21 Comment(1)
@component seems nice if you are starting a new project but if one already has an existing project that is already using a multitude of @include, then it seems like it would be chaos to try and remember which pieces are @component and which pieces are @include.Lind
O
73

As stated, there's no functional difference I was incorrect - see benjaminhull's answer for details on variable scoping and passing blade syntax code. The following still holds for basic usage, though.

If a slot could contain HTML, then using a component will give a cleaner syntax in your blade files.

@component('test')
   <strong>This text has html</strong>
@endcomponent

versus

@include('test', ['slot' => '<strong>This text has HTML</strong>'])

Equally, if a component has no slots, then an include may be preferred:

@include('test')

versus

@component('test')
@endcomponent
Oyez answered 22/12, 2017 at 9:6 Comment(4)
This is a much more useful explanation than simply referencing the docs (which frustratingly don't give any helpful use-cases). I've just picked up Laravel a couple weeks ago and am working my first project. My reason for searching this is exactly the example you provided. I have HTML that i don't care to stringify or mess with ob_start(); ... return ob_get_clean().Sacring
This is a great example. I'm struggling to simplify a complex application by building inter-connected blade layouts and this distinction is really helping me distinguish between sections and components.Heterologous
For those interested, please take a look at DavidHyogo's answer. He provides an excelent point that should be considered.Dhruv
"there's no functional difference" - this isn't true. See mine and other answers. Respectfully, please update your answer since it is not correct.Scrotum
S
29

There are two key differences.

1. Variable scope

As described in @DavidHyogo's answer, a component only sees variables explicitly passed to it. So you have to give it all variables like so...

@component('my-component', ['foo' => 'bar', 'etc' => 'etc'])

Whereas an include will adopt all variables from the global/current scope by default - unless you define an explicit set of variables to pass it, which then becomes local scope again.

{{-- This include will see all variables from the global/current scope --}}
@include('my-component')

{{-- This include will only see the variables explicitly passed in --}}
@include('my-component', ['foo' => 'bar', 'etc' => 'etc']) 

2. Component's {{ $slot }} vs include's {{ $var }}

When using a {{ $slot }} in a component, you can give it blade syntax code e.g...

{{-- alert.blade.php --}}
<div class="alert">{{ $slot }}</div>

@component('alert')
    <div>Hello {{ $name }} @include('welcome-message')</div>
@endcomponent

Note how the slot will receive html AND blade syntax code and just deal with it.

This is not possible with includes because you can only pass variables into includes...

{{-- alert.blade.php --}}
<div class="alert">{{ $slot }}</div>

@include('alert', ['slot' => "I CAN'T PASS IN BLADE SYNTAX HERE!"])

It could be done in a more hacky way by grabbing a fresh view() helper and passing it some variables to compile the output we want to pass into the slot, but this is what components are for.

Scrotum answered 23/6, 2020 at 21:35 Comment(0)
H
24

I think I've tracked down another crucial difference. For instance, from the documentation for 5.4:

Blade's @include directive allows you to include a Blade view from within another view. All variables that are available to the parent view will be made available to the included view:

As far as I can tell, components have a different scope from a containing view and so the variables available to the parent view are not available within the component. You need to pass a variable to a component like this:

@component('alert', ['foo' => 'bar'])
@endcomponent

This discussion is related to this problem: Use variables inside the Markdown Mailables

Heterologous answered 25/1, 2018 at 8:12 Comment(1)
This is good, but there is more to it still. Check my answer above.Scrotum
A
7

As the documentation says:

Components and slots provide similar benefits to sections and layouts; however, some may find the mental model of components and slots easier to understand.

Alfonse answered 27/5, 2017 at 2:29 Comment(2)
I've read the documentation too, and that sentence didn't really help me distinguish between the two. I think Rick's really helps to unpack these two approaches with a very practical example.Heterologous
That is about "Components and slots" vs "sections and layouts"; not about "includes"Parian
B
0

For me most important thing is component needs a class. So when I need just a simplest reusable part of html (blade) there is no need to create blade file + php file, just simple @include with subview is enough ;)

Bootjack answered 29/8, 2020 at 18:28 Comment(2)
Components do not need classes, you can have just a blade file. They also don't need a blade file and can have just a class.Changsha
Similar to inline components, anonymous components provide a mechanism for managing a component via a single file. However, anonymous components utilize a single view file and have no associated class. Source: laravel.com/docs/9.x/blade#anonymous-componentsShiner

© 2022 - 2024 — McMap. All rights reserved.