小部件概览
简介
Filament 允许你构建由"小部件"组成的动态仪表盘。每个小部件是仪表盘上的一个元素,以特定方式显示数据。例如,你可以显示统计概览、图表或表格。

创建小部件
要创建小部件,可以使用 make:filament-widget 命令:
php artisan make:filament-widget MyWidget
此命令会询问你想要创建哪种类型的小部件。你可以从以下选项中选择:
小部件排序
每个小部件类都包含一个 $sort 属性,可用于更改其在页面上相对于其他小部件的顺序:
protected static ?int $sort = 2;
自定义仪表盘页面
如果你想自定义仪表盘类,例如更改小部件列数,可以在 app/Filament/Pages/Dashboard.php 创建一个新文件:
<?php
namespace App\Filament\Pages;
use Filament\Pages\Dashboard as BaseDashboard;
class Dashboard extends BaseDashboard
{
// ...
}
最后,从配置文件中移除原始的 Dashboard 类:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
->pages([]);
}
如果你没有在创建新仪表盘类的目录中使用 discoverPages() 发现页面,你应该在 pages() 方法中手动注册该类:
use App\Filament\Pages\Dashboard;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->pages([
Dashboard::class,
]);
}
创建多个仪表盘
如果你想创建多个仪表盘,可以通过重复上述过程来实现。创建扩展 Dashboard 类的新页面将允许你创建任意数量的仪表盘。
你还需要定义额外仪表盘的 URL 路径,否则它将位于 /:
protected static string $routePath = 'finance';
你还可以通过覆盖 $title 属性来自定义仪表盘的标题:
protected static ?string $title = 'Finance dashboard';
显示给用户的主要仪表盘是他们有权访问的第一个仪表盘(由 canAccess() 方法控制),按照定义的导航排序顺序。
仪表盘的默认排序顺序是 -2。你可以使用 $navigationSort 控制自定义仪表盘的排序顺序:
protected static ?int $navigationSort = 15;
自定义小部件网格
你可以更改用于显示小部件的网格列数。
首先,你必须替换原始的仪表盘页面。
现在,在你新的 app/Filament/Pages/Dashboard.php 文件中,你可以覆盖 getColumns() 方法来返回要使用的网格列数:
public function getColumns(): int | array
{
return 2;
}
响应式小部件网格
你可能希望根据浏览器的响应式断点来更改小部件网格列数。你可以使用一个数组来实现,该数组包含每个断点应使用的列数:
public function getColumns(): int | array
{
return [
'md' => 4,
'xl' => 5,
];
}
这与响应式小部件宽度配合得很好。
自定义小部件宽度
你可以使用 $columnSpan 属性自定义小部件的宽度。你可以使用 1 到 12 之间的数字来表示小部件应跨越多少列,或使用 full 使其占据页面的全部宽度:
protected int | string | array $columnSpan = 'full';
响应式小部件宽度
你可能希望根据浏览器的响应式断点来更改小部件宽度。你可以使用一个数组来实现,该数组包含小部件在每个断点应占据的列数:
protected int | string | array $columnSpan = [
'md' => 2,
'xl' => 3,
];
在使用响应式小部件网格时,这尤其有用。

条件隐藏小部件
你可以覆盖小部件上的静态 canView() 方法来有条件地隐藏它们:
public static function canView(): bool
{
return auth()->user()->isAdmin();
}
表格小部件
你可以轻松地将表格添加到仪表盘中。首先使用命令创建一个小部件:
php artisan make:filament-widget LatestOrders --table
你现在可以通过编辑小部件文件来自定义表格。
自定义小部件
要开始构建 BlogPostsOverview 小部件:
php artisan make:filament-widget BlogPostsOverview
此命令将创建两个文件 - Filament 目录的 /Widgets 目录中的小部件类,以及 Filament 视图目录的 /widgets 目录中的视图。
该类是一个 Livewire 组件,因此你可以使用任何 Livewire 功能。Blade 视图可以包含任何你喜欢的 HTML,你可以在视图中访问任何公共 Livewire 属性。你还可以在视图中使用 $this 访问 Livewire 组件实例。
过滤小部件数据
你可以向仪表盘添加一个表单,允许用户过滤所有小部件显示的数据。当过滤器更新时,小部件将使用新数据重新加载。
首先,你必须替换原始的仪表盘页面。
现在,在你新的 app/Filament/Pages/Dashboard.php 文件中,你可以添加 HasFiltersForm trait,并添加 filtersForm() 方法来返回表单组件:
use Filament\Forms\Components\DatePicker;
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
class Dashboard extends BaseDashboard
{
use HasFiltersForm;
public function filtersForm(Schema $schema): Schema
{
return $schema
->components([
Section::make()
->schema([
DatePicker::make('startDate'),
DatePicker::make('endDate'),
// ...
])
->columns(3),
]);
}
}

在需要过滤器数据的小部件类中,你需要添加 InteractsWithPageFilters trait,这将允许你使用 $this->pageFilters 属性访问过滤表单的原始数据:
use App\Models\BlogPost;
use Carbon\CarbonImmutable;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use Illuminate\Database\Eloquent\Builder;
class BlogPostsOverview extends StatsOverviewWidget
{
use InteractsWithPageFilters;
public function getStats(): array
{
$startDate = $this->pageFilters['startDate'] ?? null;
$endDate = $this->pageFilters['endDate'] ?? null;
return [
StatsOverviewWidget\Stat::make(
label: 'Total posts',
value: BlogPost::query()
->when($startDate, fn (Builder $query) => $query->whereDate('created_at', '>=', $startDate))
->when($endDate, fn (Builder $query) => $query->whereDate('created_at', '<=', $endDate))
->count(),
),
// ...
];
}
}
$this->pageFilters 数组将始终反映当前的表单数据。请注意,此数据未经验证,因为它是实时可用的,仅用于查询数据库。你必须在使用前确保数据有效。在此示例中,我们在查询中使用开始日期之前检查其是否已设置。
使用操作模态框过滤小部件数据
或者,你可以将过滤表单替换为操作模态框,通过点击页面标题中的按钮来打开。使用此方法有很多好处:
- 过滤表单并不总是可见的,这允许你使用页面的全部高度来显示小部件。
- 过滤器在用户点击"应用"按钮之前不会更新小部件,这意味着小部件在用户准备好之前不会重新加载。如果小部件加载成本很高,这可以提高性能。
- 可以对过滤表单执行验证,这意味着小部件可以依赖数据有效的事实 - 用户在验证通过之前无法提交表单。取消模态框将丢弃用户的更改。
要使用操作模态框而不是过滤表单,你可以使用 HasFiltersAction trait 代替 HasFiltersForm。然后,在 getHeaderActions() 中注册 FilterAction 类作为操作:
use Filament\Forms\Components\DatePicker;
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Actions\FilterAction;
use Filament\Pages\Dashboard\Concerns\HasFiltersAction;
class Dashboard extends BaseDashboard
{
use HasFiltersAction;
protected function getHeaderActions(): array
{
return [
FilterAction::make()
->schema([
DatePicker::make('startDate'),
DatePicker::make('endDate'),
// ...
]),
];
}
}
处理来自过滤操作的数据与处理来自过滤标题表单的数据相同,只是数据在传递给小部件之前会经过验证。InteractsWithPageFilters trait 仍然适用。

在用户会话中持久化小部件过滤器
默认情况下,应用的仪表盘过滤器将在页面加载之间的用户会话中持久化。要禁用此功能,请在仪表盘页面类中覆盖 $persistsFiltersInSession 属性:
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
class Dashboard extends BaseDashboard
{
use HasFiltersForm;
protected bool $persistsFiltersInSession = false;
}
或者,在仪表盘页面类中覆盖 persistsFiltersInSession() 方法:
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
class Dashboard extends BaseDashboard
{
use HasFiltersForm;
public function persistsFiltersInSession(): bool
{
return false;
}
}
禁用默认小部件
默认情况下,仪表盘上会显示两个小部件。可以通过更新配置的 widgets() 数组来禁用这些小部件:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->widgets([]);
}