SelectFilter limit

From our discussion in chat: Running into an interesting issue with Select inside a Filter. If you use getSearchResultsUsing() because you need to limit the amount of results, then when you choose the option, it briefly shows the field, but then switches to the id. This only happens when inside a filter. You need to use getSearchResultsUsing because optionLimit doesn't actually limit the number of models...it still loads them all and just displays whatever limit you set. The workaround I've found is that you need to use options() and then make sure the id is included using whereIn. The docs seems to imply that if you need to limit options you need to use getSearchResults() . So maybe optionsLimit() not actually limiting the number of models being loaded isn't a big. However, it the weird thing you can see in the video does seem to be a bug, or at least a weird livewire/alpint/choices.js issue. I'll try to investigate later.
8 Replies
Kenneth Sese
Kenneth Sese14mo ago
Here's the original filter:
Tables\Filters\SelectFilter::make('user_id')
->label('Owner')
->relationship('user', 'name')
->multiple(),
Tables\Filters\SelectFilter::make('user_id')
->label('Owner')
->relationship('user', 'name')
->multiple(),
Works of course, BUT it loads ALL the users. adding optionsLimit() does not help. It still loads all the users, but only shows whatever limit you put in. You can open your console and see all the users loaded in the dom. Currently I've created my a custom Filter:
class UserSelectFilter extends SelectFilter
{
protected function getFormField(): Select
{
$field = Select::make($this->isMultiple() ? 'values' : 'value')
->multiple($this->isMultiple())
->label($this->getLabel())
->placeholder($this->getPlaceholder())
->searchable()
->options(function ($state) {
return User::query()
->whereIn('id', $state)
->orderBy('name')
->pluck('name', 'id');
})
->getSearchResultsUsing(fn (string $search) => User::where('name', 'like', "%{$search}%")->pluck('name', 'id'));

if (filled($defaultState = $this->getDefaultState())) {
$field->default($defaultState);
}

return $field;
}
}
class UserSelectFilter extends SelectFilter
{
protected function getFormField(): Select
{
$field = Select::make($this->isMultiple() ? 'values' : 'value')
->multiple($this->isMultiple())
->label($this->getLabel())
->placeholder($this->getPlaceholder())
->searchable()
->options(function ($state) {
return User::query()
->whereIn('id', $state)
->orderBy('name')
->pluck('name', 'id');
})
->getSearchResultsUsing(fn (string $search) => User::where('name', 'like', "%{$search}%")->pluck('name', 'id'));

if (filled($defaultState = $this->getDefaultState())) {
$field->default($defaultState);
}

return $field;
}
}
If ->options() is not there you get the issue in the video. Used like this in the Resource:
UserSelectFilter::make('user_id')
->label('Owner')
->relationship('user', 'name')
->multiple(),
UserSelectFilter::make('user_id')
->label('Owner')
->relationship('user', 'name')
->multiple(),
Mark Chaney
Mark Chaney14mo ago
@kennethsese you can also just do your own form for the filter. I rarely use SelectFilter and strictly use Filter::make()->form() or something similar seems easier than extending a class
Dan Harrin
Dan Harrin14mo ago
@kennethsese maybe you need to define getOptionLabelUsing() and getOptionLabelsUsing(), which the select will use to fill in the gaps where it doesnt have a label for a particular ID
Kenneth Sese
Kenneth Sese14mo ago
That didn’t make a difference unfortunately Well the first one didn’t…I’ll try the latter.
Dan Harrin
Dan Harrin14mo ago
you will need both if its single OR multiple we convert either 1 value or multiple at once
Kenneth Sese
Kenneth Sese14mo ago
In my case I'm forcing it to always do multiple which is why the getOptionLabelUsing() wasn't working. getOptionLabelsUsing()does work and is the way to go. I knew I missing something. You're the best Dan! And correct me if I'm wrong, but this can be used with options() to have say the first 10 models loaded.
Dan Harrin
Dan Harrin14mo ago
exactly check out the implementation of the relationship() Select method internally to see how we use it
Kenneth Sese
Kenneth Sese14mo ago
And UGGGHHHHH ...it's right there in the docs under multi-select...frustrating when I miss stuff like that. @awcodes Dan figured out what I was doing wrong. As you suspected, something was off. Thanks for helping!