F
Filamentβ€’9mo ago
HL

Modify SelectFilter query based on another SelectFilters value (Dependent Filters)

I have these 2 filters ( in my app:
SelectFilter::make('game')
->relationship('games', 'name'),

SelectFilter::make('server')
->relationship(
name: 'servers',
titleAttribute: 'abbrevation',
modifyQueryUsing: function (Builder $query) {
return $query->orderBy('servers.game', 'asc')->orderBy('servers.id', 'asc');
}
),
SelectFilter::make('game')
->relationship('games', 'name'),

SelectFilter::make('server')
->relationship(
name: 'servers',
titleAttribute: 'abbrevation',
modifyQueryUsing: function (Builder $query) {
return $query->orderBy('servers.game', 'asc')->orderBy('servers.id', 'asc');
}
),
I want to make the 2nd filter so, that it only queries the servers, which are selected by the first selectFilter, or otherwise show all. I can do that with custom filters, but is there some out of the box solution for this?
6 Replies
HL
HLβ€’9mo ago
Yes to use this I need custom filters with queries that I need to write myself, that was the point of the question, if I can avoid it
Matt Jenkins
Matt Jenkinsβ€’8mo ago
I'm after the same thing, did you ever find a solution to this?
HL
HLβ€’8mo ago
I did it with custom filters, no easy way to do it You need to do a Filter, and make a form for it with multiple Select fields
Filter::make('accounts')
->form([
Grid::make(2)
->schema([
Select::make('game')
->relationship('games', 'name')
->live()
->placeholder('All'),

Select::make('server')
->relationship(
name: 'servers',
titleAttribute: 'name',
modifyQueryUsing: function (Builder $query, Get $get) {
if ($get('game') != null) {
return $query->where('servers.game', $get('game'))->orderBy('servers.game', 'asc')->orderBy('servers.id', 'asc');
} else {
return $query->orderBy('servers.game', 'asc')->orderBy('servers.id', 'asc');
};
}
)
->live()
->placeholder('All'),
]),
])
Filter::make('accounts')
->form([
Grid::make(2)
->schema([
Select::make('game')
->relationship('games', 'name')
->live()
->placeholder('All'),

Select::make('server')
->relationship(
name: 'servers',
titleAttribute: 'name',
modifyQueryUsing: function (Builder $query, Get $get) {
if ($get('game') != null) {
return $query->where('servers.game', $get('game'))->orderBy('servers.game', 'asc')->orderBy('servers.id', 'asc');
} else {
return $query->orderBy('servers.game', 'asc')->orderBy('servers.id', 'asc');
};
}
)
->live()
->placeholder('All'),
]),
])
Then a query for it
->query(function (Builder $query, array $data): Builder {
return $query
->when(
$data['game'],
fn (Builder $query, $game) => $query->whereHas(
'games',
fn (Builder $query) => $query->where('games.id', $game)
)
)
->when(
$data['server'],
fn (Builder $query, $server) => $query->whereHas(
'servers',
fn (Builder $query) => $query->where('servers.id', $server)
)
);
})
->query(function (Builder $query, array $data): Builder {
return $query
->when(
$data['game'],
fn (Builder $query, $game) => $query->whereHas(
'games',
fn (Builder $query) => $query->where('games.id', $game)
)
)
->when(
$data['server'],
fn (Builder $query, $server) => $query->whereHas(
'servers',
fn (Builder $query) => $query->where('servers.id', $server)
)
);
})
Then you need an indicator for it
->indicateUsing(function (array $data): array {
$indicators = [];
if ($data['game'] ?? null) {
$indicators['game'] = 'Game: ' . Game::find($data['game'])->displayname;
};
if ($data['server'] ?? null) {
$indicators['server'] = 'Server: ' . Server::find($data['server'])->abbrevation;
};
return $indicators;
}),
->indicateUsing(function (array $data): array {
$indicators = [];
if ($data['game'] ?? null) {
$indicators['game'] = 'Game: ' . Game::find($data['game'])->displayname;
};
if ($data['server'] ?? null) {
$indicators['server'] = 'Server: ' . Server::find($data['server'])->abbrevation;
};
return $indicators;
}),
Matt Jenkins
Matt Jenkinsβ€’8mo ago
Fantastic, I'd actually gone down that road before but completely forgot.
Pasteko
Pastekoβ€’5mo ago
Thanks for your work, it helped me a lot today! πŸ™‚