Reputation: 2101
Is it possible to pass a variable from component into a slot. Here is an example:
{{-- index.blade.php --}}
@component('slider', ['entities' => [0, 1, 2]])
@slot('title')
Slider title
@endslot
@slot('slide')
Slider content no {{ $entity }}
@endslot
@endcomponent
{{-- slider.blade.php --}}
<h1>{{ $title }}</h1>
<ul>
@foreach($entities as $entity)
<li>{{ $slide }}</li>
@endforeach
</ul>
Current result :
Exception : $entity is not defined
Expected result:
<h1>Slider title</h1>
<ul>
<li>Slider content no 0</li>
<li>Slider content no 1</li>
<li>Slider content no 2</li>
</ul>
Upvotes: 15
Views: 28239
Reputation: 1229
UPDATE: I created a package adding scoped slots feature to Blade. Your problem is a perfect use-case for the scoped slots and it can be easily resolved using them. Check it out.
I struggled with the same problem and finally I found a way to "pass" variables from component to slot. The trick is to use @verbatim
directive which makes blade code not compile. Therefore we're able to pass blade code to a slot and then compile it in our component. However there is only one condition -- the name of variable used in foreach
loop has to be the same as the one used in the slot. (As shown in the example below -- the slide
slot uses $entity
variable and so does the foreach
loop in the component)
index.blade.php
@component('slider', ['entities' => [0, 1, 2]])
@slot('title')
Slider title
@endslot
@slot('slide')
@verbatim
Slide {{ $entity }}
@if ($entity === 0) {{-- Directives also work! --}}
<strong>Special slide</strong>
@endif
@endverbatim
@endslot
@endcomponent
slider.blade.php
<h1>{{ $title }}</h1>
<ul>
@foreach($entities as $entity)
<li>{!! eval('?>'.Blade::compileString($slide)) !!}</li>
@endforeach
</ul>
It is a little "hacky" solution to the problem but most importantly it does the job as you can see on the screenshot below.
Upvotes: 2
Reputation: 536
It seems that there is no way to pass data from a component to a slot context. It is also the case with @section
/@yield
.
What I've discovered is the @each
function. https://laravel.com/docs/5.6/blade#rendering-views-for-collections
You'd need to have another view partial for the list item content (called item
here).
{{-- index.blade.php --}}
@component('slider', ['entities' => [0, 1, 2], 'item_view' => 'item'])
@slot('title')
Slider title
@endslot
@endcomponent
{{-- item.blade.php --}}
<li>
Slider content no $entity
</li>
{{-- slider.blade.php --}}
<h1>{{ $title }}</h1>
<ul>
@each($item_view, $entities, 'entity')
</ul>
Example: making a new slider with different content:
{{-- gallery.blade.php --}}
@component('slider', ['entities' => ['a.png', 'b.png', 'c.png'], 'item_view' => 'gallery_item'])
@slot('title')
Gallery
@endslot
@endcomponent
{{-- gallery_item.blade.php --}}
<li>
<img src={{ $entity }} />
</li>
Upvotes: 7
Reputation: 1534
We can try with different way. Here, how I executed.
{{-- index.blade.php --}}
@component('slider', ['entities' => [0, 1, 2]])
@slot('title')
Slider title
@endslot
@slot('slide')
Slider content no
@endslot
@endcomponent
{{-- slider.blade.php --}}
<h1>{{ $title }}</h1>
<ul>
@foreach($entities as $entity)
<li>{{ $slide }} {{ $entity }}</li>
@endforeach
</ul>
Upvotes: 2