Widget
概述
简介
Filament 允许你创建由 Widget 组成的动态仪表盘。Widget 是仪表盘上以特定方式显示数据的元素。比如,你可以展示统计数据、图表或表格。
创建 Widget
要创建 Widget,你可以使用 make:filament-widget
命令:
php artisan make:filament-widget MyWidget
该命令将会询问你想创建哪种类型的 Widget。以下是你可以选择的选项:
Widget 排序
每个 Widget 类都包含一个 $sort
属性,你可以用它来修改其在页面中相对于其他 Widget 的排序。
protected static ?int $sort = 2;
自定义仪表盘页面
如果你想自定义仪表盘类,比如,修改 Widget 列的数量,请新建 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';
The primary dashboard shown to a user is the first one they have access to (controlled by canAccess()
method), according to the defined navigation sort order.
The default sort order for dashboards is -2
. You can control the sort order of custom dashboards with $navigationSort
:
protected static ?int $navigationSort = 15;
自定义 Widget 网格
You may change how many grid columns are used to display widgets.
Firstly, you must replace the original Dashboard page.
Now, in your new app/Filament/Pages/Dashboard.php
file, you may override the getColumns()
method to return a number of grid columns to use:
public function getColumns(): int | string | array
{
return 2;
}
响应式 Widget 网格
You may wish to change the number of widget grid columns based on the responsive breakpoint of the browser. You can do this using an array that contains the number of columns that should be used at each breakpoint:
public function getColumns(): int | string | array
{
return [
'md' => 4,
'xl' => 5,
];
}
This pairs well with responsive widget widths.
自定义 Widget 宽度
You may customize the width of a widget using the $columnSpan
property. You may use a number between 1 and 12 to indicate how many columns the widget should span, or full
to make it occupy the full width of the page:
protected int | string | array $columnSpan = 'full';
响应式 Widget 宽度
You may wish to change the widget width based on the responsive breakpoint of the browser. You can do this using an array that contains the number of columns that the widget should occupy at each breakpoint:
protected int | string | array $columnSpan = [
'md' => 2,
'xl' => 3,
];
This is especially useful when using a responsive widgets grid.
条件性隐藏 Widget
You may override the static canView()
method on widgets to conditionally hide them:
public static function canView(): bool
{
return auth()->user()->isAdmin();
}
表格 Widget
使用如下 Widget 创建命令,你可以添加表格到仪表盘中:
php artisan make:filament-widget LatestOrders --table
现在你可以编辑 Widget 文件自定义表格。
自定义 Widget
创建 BlogPostsOverview
Widget:
php artisan make:filament-widget BlogPostsOverview
该命令将生成两个文件 —— 在 Filament 目录下的 Widgets
目录中生成一个 Widget 类,以及在 Filament 视图目录的 widgets
目录中生成一个视图文件。
该类是一个 Livewire 组件,因此 Livewire 的所有特性都是可用的。Blade 视图可以包含任何你希望使用的 HTML,并且你可以在视图中访问所有公开的 Livewire 属性。你也可以在视图中使用 $this
访问 Livewire 组件实例。
过滤 Widget 数据
You may add a form to the dashboard that allows the user to filter the data displayed across all widgets. When the filters are updated, the widgets will be reloaded with the new data.
Firstly, you must replace the original Dashboard page.
Now, in your new app/Filament/Pages/Dashboard.php
file, you may add the HasFiltersForm
trait, and add the filtersForm()
method to return form components:
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),
]);
}
}
In widget classes that require data from the filters, you need to add the InteractsWithPageFilters
trait, which will allow you to use the $this->pageFilters
property to access the raw data from the filters form:
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(),
),
// ...
];
}
}
The $this->pageFilters
array will always reflect the current form data. Please note that this data is not validated, as it is available live and not intended to be used for anything other than querying the database. You must ensure that the data is valid before using it. In this example, we check if the start date is set before using it in the query.
使用 Action 模态框过滤 Widget 数据
Alternatively, you can swap out the filters form for an action modal, that can be opened by clicking a button in the header of the page. There are many benefits to using this approach:
- The filters form is not always visible, which allows you to use the full height of the page for widgets.
- The filters do not update the widgets until the user clicks the “Apply” button, which means that the widgets are not reloaded until the user is ready. This can improve performance if the widgets are expensive to load.
- Validation can be performed on the filters form, which means that the widgets can rely on the fact that the data is valid - the user cannot submit the form until it is. Canceling the modal will discard the user’s changes.
To use an action modal instead of a filters form, you can use the HasFiltersAction
trait instead of HasFiltersForm
. Then, register the FilterAction
class as an action in getHeaderActions()
:
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()
->form([
DatePicker::make('startDate'),
DatePicker::make('endDate'),
// ...
]),
];
}
}
Handling data from the filter action is the same as handling data from the filters header form, except that the data is validated before being passed to the widget. The InteractsWithPageFilters
trait still applies.
Persisting widget filters in the user’s session
By default, the dashboard filters applied will persist in the user’s session between page loads. To disable this, override the $persistsFiltersInSession
property in the dashboard page class:
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
class Dashboard extends BaseDashboard
{
use HasFiltersForm;
protected bool $persistsFiltersInSession = false;
}
Alternatively, override the persistsFiltersInSession()
method in the dashboard page class:
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
class Dashboard extends BaseDashboard
{
use HasFiltersForm;
public function persistsFiltersInSession(): bool
{
return false;
}
}
禁用默认 Widget
By default, two widgets are displayed on the dashboard. These widgets can be disabled by updating the widgets()
array of the configuration:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->widgets([]);
}
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion