过滤器
概述
过滤器(Filter)允许你在数据上定义特定的约束,并允许用户限定查询范围,以查找他们所需的信息。可以在 $table->filters()
方法中定义过滤器:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->filters([
// ...
]);
}
过滤器可以使用静态的 make()
方法创建,并传入其唯一名。然后你应该传入一个回调函数到 query()
中,设置过滤器的查询范围:
use Filament\Tables\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;
Filter::make('is_featured')
->query(fn (Builder $query): Builder => $query->where('is_featured', true))
设置标签
默认情况下,过滤器的标签是有过滤器名生成。你可以使用 label()
方法自定义该标签:
use Filament\Tables\Filters\Filter;
Filter::make('is_featured')
->label('Featured')
可选地,你可以使用 translateLabel()
方法,使其利用 Laravel 的本地化特性自动翻译标签。
use Filament\Tables\Filters\Filter;
Filter::make('is_featured')
->translateLabel() // Equivalent to `label(__('Is featured'))`
自定义过滤器表单
默认情况下,使用 Filter
类创建过滤器会渲染一个 Chcekbox 表单组件。当 Checkbox 被勾选后,query()
函数将会使用表格的查询,过滤表格中的记录。如果 Checkbox 未被勾选,query()
函数会从表格查询中删除。
过滤器完全是建立在 Filament 表单字段之上。他们可以渲染任何表单字段的组合,使用户可以直接交互过 滤表格。
使用 Toggle 按钮代替 Checbox
管理用于过滤器的表单字段的最简单示例是,使用 Toggle 按钮替换 Checkbox:
use Filament\Tables\Filters\Filter;
Filter::make('is_featured')
->toggle()
默认使用过滤器
使用 default()
方法,你可以设置默认启用过滤器:
use Filament\Tables\Filters\Filter;
Filter::make('is_featured')
->default()
Select 过滤器
有时候,你会使用 Select 字段而非 Checkbox。当您希望用户可以根据一组预定义选项过滤列字段时,尤其如此。为此,您可以使用 SelectFilter
类创建一个过滤器:
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
通过 options()
传递给过滤器的选项,与传递给 Select 字段的方式一致:
自定义 SelectFilter 使用的列字段
SelectFilter 不需要自定义 query()
方法。查询所使用的列字段名是过滤器名称。要自定义字段名,请使用 attribute()
方法:
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('status')
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
->attribute('status_id')
多选 SelectFilter
这将允许用户选择多个选项,应用到过滤器。比如,状态过滤器可能向用户展示一些状态选项供用户选取及表格过滤使用。当用户选择多个选项时,表格会过滤显示匹配所选选项的记录。你可以使用 multiple()
方法启用该行为:
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('status')
->multiple()
->options([
'draft' => 'Draft',
'reviewing' => 'Reviewing',
'published' => 'Published',
])
关联 SelectFilter
SelectFilter 也能够基于关联自动填充。比如,如果表有一个 author
关联,它有一个 name
字段,你可以使用 relationship()
过滤属于某个作者(author)的记录:
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('author')
->relationship('author', 'name')
预加载 SelectFilter 关联选项
如果你想在页面加载时填充可搜索选项,而不是在用户搜索时加载,你可以使用 preload()
方法:
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('author')
->relationship('author', 'name')
->searchable()
->preload()
自定义 SelectFilter 关联查询
使用 relationship()
方法的第三个参数,你可以自定义用于检索选项的数据库查询:
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Database\Eloquent\Builder;
SelectFilter::make('author')
->relationship('author', 'name', fn (Builder $query) => $query->withTrashed())
搜索 SelectFilter 选项
使用 searchable()
方法,你可以启用搜索输入框,以方便访问选项:
use Filament\Tables\Filters\SelectFilter;
SelectFilter::make('author')
->relationship('author', 'name')
->searchable()
三元过滤器
三元过滤器(TernaryFilter)允许你创建一个拥有三个状态(通常为 true、false 及空白)的 Select 过滤器。要将名为 is_admin
的字段过滤为 true
或 false
,你可以使用三元过滤器:
use Filament\Tables\Filters\TernaryFilter;
TernaryFilter::make('is_admin')
nullable 字段使用三元过滤器
另一个通用的模式是使用 nullable 字段。比如,使用 email_verified_at
来过滤验证及未验证的用户,未验证的用户在本字段中为空时间戳。要应用该逻辑,你可以使用 nullable()
方法:
use Filament\Tables\Filters\TernaryFilter;
TernaryFilter::make('email_verified_at')
->nullable()
自定义三元过滤器使用的列字段
用于设置查询范围的字段名是过滤器的名称。要自定义字段名,你可以使用 attribute()
方法:
use Filament\Tables\Filters\TernaryFilter;
TernaryFilter::make('verified')
->nullable()
->attribute('status_id')
自定义三元过滤器选项标签
你可以自定义三元过滤器每个状态的标签。true 选项的标签可以使用 trueLabel()
方法自定义。false 选项可以使用 falseLabel()
方法自定义。空白(默认)选项的标签可以使用 placeholder()
方法自定义:
use Illuminate\Database\Eloquent\Builder;
use Filament\Tables\Filters\TernaryFilter;
TernaryFilter::make('email_verified_at')
->label('Email verification')
->nullable()
->placeholder('All users')
->trueLabel('Verified users')
->falseLabel('Not verified users')
自定义三元过滤器修改查询的方式
使用 queries()
方法,你可以自定义三元过滤器的每个状态查询的修改方式:
use Illuminate\Database\Eloquent\Builder;
use Filament\Tables\Filters\TernaryFilter;
TernaryFilter::make('trashed')
->placeholder('Without trashed records')
->trueLabel('With trashed records')
->falseLabel('Only trashed records')
->queries(
true: fn (Builder $query) => $query->withTrashed(),
false: fn (Builder $query) => $query->onlyTrashed(),
blank: fn (Builder $query) => $query->withoutTrashed(),
)
自定义过滤器表单
你可以使用表单构造器的组件,创建自定义过滤器表单。自定义过滤器表单中的数据,可以在 query()
回调中的 $data
数组中获取:
use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;
use Illuminate\Database\Eloquent\Builder;
Filter::make('created_at')
->form([
DatePicker::make('created_from'),
DatePicker::make('created_until'),
])
->query(function (Builder $query, array $data): Builder {
return $query
->when(
$data['created_from'],
fn (Builder $query, $date): Builder => $query->whereDate('created_at', '>=', $date),
)
->when(
$data['created_until'],
fn (Builder $query, $date): Builder => $query->whereDate('created_at', '<=', $date),
);
})
设置自定义过滤器字段的默认值
要在自定义过滤器表单中自定义默认值,你可以使用 default()
方法:
use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;
Filter::make('created_at')
->form([
DatePicker::make('created_from'),
DatePicker::make('created_until')
->default(now()),
])
激活指示器
当过滤器出于激活状态时,在表格内容上面会显示一个指示器,说明表格的查询范围已限定。
默认情况下,过滤器的标签被用作指示器。你可以使用 indicator()
方法对此进行重写:
use Filament\Tables\Filters\Filter;
Filter::make('is_admin')
->label('Administrators only?')
->indicator('Administrators')
自定义激活指示器
并非所有的指示器都很简单,因此您可能需要使用 indicateUsing()
来自定义在哪个时候显示哪个指示器。
例如,如果您有一个自定义日期过滤器,您可以创建一个自定义指示器来格式化所选日期:
use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;
Filter::make('created_at')
->form([DatePicker::make('date')])
// ...
->indicateUsing(function (array $data): ?string {
if (! $data['date']) {
return null;
}
return 'Created at ' . Carbon::parse($data['date'])->toFormattedDateString();
})
多个激活指示器
你甚至可以通过返回 Indicator
对象数组,一次性渲染多个指示器。如果你有关联不同指示器的不同字段,你应该使用字段名作为数组键,以确保过滤器移除时重置的字段正确:
use Filament\Forms\Components\DatePicker;
use Filament\Tables\Filters\Filter;
Filter::make('created_at')
->form([
DatePicker::make('from'),
DatePicker::make('until'),
])
// ...
->indicateUsing(function (array $data): array {
$indicators = [];
if ($data['from'] ?? null) {
$indicators['from'] = 'Created from ' . Carbon::parse($data['from'])->toFormattedDateString();
}
if ($data['until'] ?? null) {
$indicators['until'] = 'Created until ' . Carbon::parse($data['until'])->toFormattedDateString();
}
return $indicators;
})
将过滤器定位到网格列中
要修改过滤器占用的列数,你可以使用 filtersFormColumns()
方法:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->filters([
// ...
])
->filtersFormColumns(3);
}
控制过滤器下拉菜单的宽度
要自定义下拉菜单的宽度,你可以使用 filtersFormWidth()
方法,并指定一个宽度 - xs
、sm
、md
、lg
、xl
、2xl
、3xl
、4xl
、5xl
、6xl
或 7xl
。默认宽度是 xs
:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->filters([
// ...
])
->filtersFormWidth('4xl');
}