laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.17k stars 10.88k forks source link

how pass data to x-slot? #37758

Closed miladkhodaverdi23 closed 3 years ago

miladkhodaverdi23 commented 3 years ago

Description:

I want to pass a variable to the x-slot The slot is rendered before the component is rendered . why? is big problem :(((((

components\data-table.blade.php

<div >
    <table id="{{$id}}" class="table">
        <thead class="thead-light">
        <tr>
            @foreach($columns as $column)
                 {{$test1}}
            @endforeach
        </tr>
        </thead>
    </table>
</div>

app.blade.php

<x-data-table
                :columns="[
                        ['title'=>'','data'=> 'id', 'orderable'=> false],
                        ['title'=>'First Name', 'data'=> 'first_name', 'orderable'=> false],
                        ['title'=>'Last Name', 'data'=> 'last_name',  'orderable'=> false],
                        ['title'=>'National Code', 'data'=> 'national_code',  'orderable'=> false],
                        ['title'=>'Phone', 'data'=> 'phone', 'orderable'=> false],
                        ['title'=>'','data'=> 'action', 'orderable'=> false]
                    ]"
                url="http://portal.test/users?section=triage&triage=true"
>
<x-slot name="test1" >
     {{$column->id}}
</x-slot>
</x-data-table>
igorgaming commented 3 years ago

Yes, I faced the same problem. Components do not pass data to their slots. Although, there are scoped slots, this does not solve the problems with foreach. Therefore, the only thing you can do is to move the foreach from the component to the slot.

driesvints commented 3 years ago

Hi there,

Thanks for reporting but it looks like this is a question which can be asked on a support channel. Please only use this issue tracker for reporting bugs with the library itself. If you have a question on how to use functionality provided by this repo you can try one of the following channels:

However, this issue will not be locked and everyone is still free to discuss solutions to your problem!

Thanks.

NorthBlue333 commented 2 years ago

Hello, My comment is about this issue and also this PR https://github.com/laravel/framework/pull/29111.

I know it is a bit old, but I'd like to add my point of view.

I agree with @Angelinsky7, we should be able to customize some display logic, in specific places decided by the component creator. In fact, as @browner12 says:

Components are responsible for the display logic. Slots are ways to pass data to the component.

This is correct, but not entirely : you may have a (big) component, i.e. a datatable with filters, headers, etc. (a lot of logic and display logic you do NOT want to be duplicating), but you may also want to allow the developer to use the component and customize what is displayed inside each cell. This can be done by echoing raw html but it is not great...

This example is what is available in Vuetify (VueJS), here is the doc https://vuetifyjs.com/en/components/data-tables/#item.

It can also be done by using a dynamic component, providing a name for the component to be rendered and pass the data to the component :

// custom.blade.php
@props(['items' => [], 'itemComponent' => null, 'itemComponentAttributes' => new \Illuminate\View\ComponentAttributeBag([])])
<div>
  @foreach ($items as $item)
    @if (isset($item['component'])
        <x-dynamic-component :component="$item['component']" :attributes="new \Illuminate\View\ComponentAttributeBag($item)" />
    @else if ($itemComponent)
        <x-dynamic-component :component="$itemComponent" :attributes="$itemComponentAttributes->merge($item)" />
    @else
      {{ $item['label'] }}
    @endif
  @€ndforeach
</div>

// item-label-red.blade.php
@props(['label'])
<div style="color: red">
    {{ $label }}
</div>

// item-label.blade.php
@props(['label'])
<div style="color: {{ $label === 'foo' ? 'green' : 'blue' }}">
    {{ $label }}
</div>

// index.blade.php
<x-custom itemComponent="item-label" :items="[['label' => 'foo'], ['label' => 'foo2'], ['label' => 'bar', 'component' => 'item-label-red']]" />

Note that you can organize your components as you want (see https://laravel.com/docs/9.x/blade#anonymous-component-namespaces).

I have also found this https://github.com/laravel/ideas/issues/2116, where the PR for @aware directive is mentioned. But this directive only allows access to component attributes and not loop variables (i.e.).

robsontenorio commented 1 year ago

@NorthBlue333 your example does not solve the original issue . Or am I missing something?

<x-slot name="test1" >
     {{$column->id}} <—- how to access current item from loop ?
</x-slot>
NorthBlue333 commented 1 year ago

@robsontenorio indeed it does not. My example does not use x-slot at all as it is a workaround using «sub-components». The code I provided should be working on its own if you want to test it.

mshamaseen commented 4 months ago

I'm facing the same issue. It is weird that this is not of interest to the community; how do you guys make dynamic tables then :thinking:

mshamaseen commented 4 months ago

ok I found a workaround for this, pass a function as an attribute and execute it in the component, like:

Base

<x-pagination.length-aware-pagination :columns="[
'name',
'status'
]" :paging="$entities">
    <x-slot:status :html="fn($entity) => $entity->status.' worked' ">

    </x-slot:status>
</x-pagination.length-aware-pagination>
@endsection

component

 @foreach($columns as $column)
    @if(isset($$column) && $$column instanceof \Illuminate\View\ComponentSlot)
        <th>{{$$column->attributes->get('html', fn() => $$column)($entity)}}</th>
    @else
        <th>{{$entity[$column]}}</th>
    @endif
@endforeach