I have a solution, but I think it's horrid, so I want to ask you if there's a better (or correct) way
I need to create a <select>
that I'll use in lots of places around my app. This <select>
is what you expect:
<select name="xxx">
<option value="">...</option>
@foreach ($equipos as $equipo)
<option value="{{ $equipo->id }}">
{{ $equipo->equipo }}
</option>
@endforeach
</select>
So, my first attempt was to use an component <x-select-equipos>
the component view will be:
<select {{ $attributes->merge(['class' => 'w-full']) }}>
<option value="">...</option>
@foreach ($equipos as $equipo)
<option value="{{ $equipo->id }}">
{{ $equipo->equipo }}
</option>
@endforeach
</select>
So I thought I could call this component like:
<x-select-equipos name="xxx" equipos="{{ $equipos }}" />
But I can't pass the $equipos
collection to the component. If I do that this way, it just sends a true
In my second try I wrote a Livewire component, but it limits me to use Laravel's ORM, so I "rendered" all the <option>
s in the component (.php), and just display them in the .blade.php
Another problem this solution has, is that I have to do a call to the database everytime I have to display a <select>
and that's suboptimal (more on that below)
I don't like it a bit, but it works, I created a <x-component>
like:
<div>
@php
use App\Models\Equipo;
$equipos = Equipo::orderBy('nombre')->get();
@endphp
<select {{ $attributes->merge(['class' => 'w-full']) }}>
<option value="">...</option>
@foreach ($equipos as $equipo)
<option value="{{ $equipo->id }}">
{{ $equipo->nombre }}
</option>
@endforeach
</select>
</div>
There are many things I don't like about the solution, among others is that it has to go to the database every time it has to render an <option>
, there's one screen where I have to load 30 selects
or so. While the number of records is very small (around 40), I still don't like it, since I find it quite inefficient.
Other possible solution is go back to the Laravel/PHP basics that would be using "partials" or @include
, and that would work fine since it will go to the database just once, in fact that was the way I did it in previous versions, I wanted to try the new approaches, either with <x-components>
or LiveWire
I'm completely sure there must be a better way.
But I can't pass the $equipos collection to the component. If I do that this way, it just sends a true
Is $equipos
not an eloquent collection? You should be able to pass a collection to your component.
What about passing a collection, along with the props to specify which field(s) on the models you want to use for the values and labels?
@props([
'items', 'value', 'label'
])
<select>
<option value="">{{ __('Please select an option ...') }}</option>
@foreach ($items as $item)
<option value="{{ $item->$value }}">{{ $item->$label }}</option>
@endforeach
</select>
Then you should be able to call your component as follows (for example):
<x-select :items="User::all()" value="id" label="email" />