Usage
Use InfiniteSelect in place of Filament's Select. The only required method is getPaginatedOptionsUsing():
use MrPunyapal\FilamentInfiniteSelect\InfiniteSelect;
InfiniteSelect::make('user_id')
->getPaginatedOptionsUsing(function (int $offset, int $limit, ?string $search) {
$query = User::query()->orderBy('name');
if ($search) {
$query->where('name', 'like', "%{$search}%");
}
$total = (clone $query)->count();
return [
'options' => $query->skip($offset)->take($limit)->pluck('name', 'id')->all(),
'hasMore' => ($offset + $limit) < $total,
];
})
->getOptionLabelUsing(fn ($value) => User::find($value)?->name);
The component sets native(false) and searchable() for you.
Closure parameters
getPaginatedOptionsUsing() receives these parameters by name:
| Parameter | Type | Description |
|---|---|---|
$offset |
int |
Number of rows to skip |
$limit |
int |
Number of rows to return, taken from perPage() |
$page |
int |
1-based page number, computed as offset / limit + 1 |
$search |
?string |
Current search term |
$query |
?string |
Alias for $search |
Standard Filament injection ($component, $get, $livewire, $record, and so on) also works. Inject only the parameters your closure declares.
Different query styles (Laravel paginate(), cursorPaginate(), remote APIs) have their own recipes on the Pagination types page.
Return value
Return an array with an options map under the options key and a boolean under hasMore:
[
'options' => ['value1' => 'Label 1', 'value2' => 'Label 2'],
'hasMore' => true,
]
Three shortcuts are supported:
- Returning a plain array with no
optionskey treats it as the options map withhasMore: false - Collections and other
Arrayablevalues are converted to arrays, so returning->pluck('name', 'id')directly is fine - The same conversions apply to the
optionsvalue itself when it is anArrayable
Detecting the next page
Comparing against a total count works but runs a second query. Fetching one extra row avoids that:
$rows = $query->skip($offset)->take($limit + 1)->get();
$hasMore = $rows->count() > $limit;
return [
'options' => $rows->take($limit)->pluck('name', 'id')->all(),
'hasMore' => $hasMore,
];
Displaying saved values
Saved selections may not be part of the loaded pages. Give the field a label resolver so they display correctly on edit forms:
// Single select
->getOptionLabelUsing(fn ($value) => User::find($value)?->name);
For multiple selection use getOptionLabelsUsing(). See Multiple selection.