F
Filament5mo ago
ward

Filtering select options on-fly

I've been working on a feature where I have a select field and based on the first selection I chose, I want the form to dynamically filter out options I have. Current concept works on filtering by first selection entity dimensions, for example, if I make a choice of 600x400, I want options to re-render with options that have the same size of 600x400. I've tried to set Select form input as live()/reactive(), added a relationships' modifyQueryUsing closure to do the filtering which yields a correct query after dumping it and I have tried to set it in ->options(... by using closure. But nothing really seems to work as options are not updating. Tried alternate solution of disabling fields which don't fit the first pick criteria, but that only works when I re-open the select - the goal should be for options to be filtered out without me re-opening the select. Is it possible?
Solution:
Ok, I found that Select isn't the best option here. If I make this for CheckboxList instead, it can properly re-render available options as my intention was. Don't think that Select is really capable of that without re-opening it.
Jump to solution
2 Replies
ward
wardOP5mo ago
Field looks like so:
Select::make('position')
->required()
->multiple()
->preload()
->live()
->options(static function (string $operation, ?array $state) {
if ($operation === 'create' && is_array($state) && count($state)) {
// Since we allow for one ad in multiple positions to have one format,
// we will limit positions based on first picked position dimensions in order
// to not create a bug where certain larger ad is shown in smaller ad spot.
$position = AdvertisementPosition::find(intval($state[0]));

return AdvertisementPosition::query()
->where('width_px', $position->width_px)
->where('height_px', $position->height_px)
->get();
}

return AdvertisementPosition::query()->tap(new ActiveAdvertisement);
})
->relationship(
name: 'positions',
modifyQueryUsing: static function (Builder $query, string $operation) {
return $operation === 'create'
? $query->tap(new AvailableAdPosition)
: $query;
}
)
Select::make('position')
->required()
->multiple()
->preload()
->live()
->options(static function (string $operation, ?array $state) {
if ($operation === 'create' && is_array($state) && count($state)) {
// Since we allow for one ad in multiple positions to have one format,
// we will limit positions based on first picked position dimensions in order
// to not create a bug where certain larger ad is shown in smaller ad spot.
$position = AdvertisementPosition::find(intval($state[0]));

return AdvertisementPosition::query()
->where('width_px', $position->width_px)
->where('height_px', $position->height_px)
->get();
}

return AdvertisementPosition::query()->tap(new ActiveAdvertisement);
})
->relationship(
name: 'positions',
modifyQueryUsing: static function (Builder $query, string $operation) {
return $operation === 'create'
? $query->tap(new AvailableAdPosition)
: $query;
}
)
Putting what I have in options does not change anything.
Solution
ward
ward5mo ago
Ok, I found that Select isn't the best option here. If I make this for CheckboxList instead, it can properly re-render available options as my intention was. Don't think that Select is really capable of that without re-opening it.
Want results from more Discord servers?
Add your server