Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing variable from component into a slot

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>
  • How can I pass the $entity variable into the slide slot?
  • Is it even possible to do so?
  • If not, are there any alternatives?
like image 783
HubertNNN Avatar asked May 25 '18 09:05

HubertNNN


3 Answers

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>
like image 105
Narayan Adhikari Avatar answered Nov 16 '22 00:11

Narayan Adhikari


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>
like image 35
Kalabasa Avatar answered Nov 16 '22 00:11

Kalabasa


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.

The result of the code above

like image 2
Konrad Kalemba Avatar answered Nov 16 '22 01:11

Konrad Kalemba