导航
概述
默认情况下,Filament 会为每一个 资源类、自定义页面 和 Clusters 注册导航菜单。这些类中包含一些你可以重写的静态属性和静态方法,用以配置导航菜单和显示顺序:
如果想在应用中添加一层导航,可以使用 Clusters。这对于资源和页面分组很有用。
自定义导航项标签
默认情况下,导航标签由资源或者页面的名字生成,你可以 使用 $navigationItems
属性自定义该标签:
protected static ?string $navigationLabel = 'Custom Navigation Label';
此外,你也可以重写 $getNavigationLabel()
方法:
public static function getNavigationLabel(): string
{
return 'Custom Navigation Label';
}
自定义导航项图标
你可以重写资源和页面类页面中的 $navigationIcon
属性,自读八卦图导航菜单项的图标:
protected static ?string $navigationIcon = 'heroicon-o-document-text';
如果你在同一个导航组内的所有项目都设置了 $navigationIcon = null
,这些项目将会通过分组标签下方的竖条(vertical bar)连接。
激活时切换导航菜单图标
使用 $activeNavigationIcon
属性,可以分配一个仅用于激活项的导航图标:
protected static ?string $activeNavigationIcon = 'heroicon-o-document-text';
导航项排序
默认情况下,导航项按照字母顺序排序,你可以使用 $navigationSort
属性自定义排序:
protected static ?int $navigationSort = 3;
c```
限制,使用低数值导航项会出现在高数值的前面 - 排序是升序的。
## 添加徽章到导航项
要在导航菜单项中添加徽章,可以使用 `getNavigaionBadge()` 方法,返回徽章内容:
```php
public static function getNavigationBadge(): ?string
{
return static::getModel()::count();
}
如果徽章值是由 getNavigationBadge()
返回,它将默认使用 primary 颜色展示。要自定义徽章上下文样式,请在 getNavigationBadgeColor()
方法中返回 danger
、gray
、info
、primary
、success
或 warning
:
public static function getNavigationBadgeColor(): ?string
{
return static::getModel()::count() > 10 ? 'warning' : 'primary';
}
导航徽章的自定义 tooltip 可以在 $navigationBadgeTooltip
中设置:
protected static ?string $navigationBadgeTooltip = 'The number of users';
或者从 getNavigationBadgeTooltip()
中返回:
public static function getNavigationBadgeTooltip(): ?string
{
return 'The number of users';
}
导航项分组
你可以通过指定资源类resources 和 自定义页面的 $navigationGroup
属性对导航菜单项进行分组:
protected static ?string $navigationGroup = 'Settings';
在同一个导航分组中的所有菜单项会被集中到同一个分组标签下显示,比如本例的 "Settings"。未分组的菜单项会被保留在侧边栏顶部。
将导航项分组到其他项目之下
将父级项目的标签传递给 $navigationParentItem
,你可以将导航项作为其他项的子项分组:
protected static ?string $navigationParentItem = 'Notifications';
protected static ?string $navigationGroup = 'Settings';
也可以使用 getNavigationParentItem()
方法设置动态的父级项目标签:
public static function getNavigationParentItem(): ?string
{
return __('filament/navigation.groups.settings.items.notifications');
}
如上所见,如果父级项目有一个导航主,导航组也必须定义,这样才能识别正确的父级项目。
如果有三级导航,你应该考虑使用 Cluster,这是资源和自定义页面的逻辑分组,可以共享自己单独的导航。
自定义导航分组
你可以在配置中调用 navigationGroups()
,并按顺序传入 NavigationGroup
对象来自定义导航分组:
use Filament\Navigation\NavigationGroup;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->navigationGroups([
NavigationGroup::make()
->label('Shop')
->icon('heroicon-o-shopping-cart'),
NavigationGroup::make()
->label('Blog')
->icon('heroicon-o-pencil'),
NavigationGroup::make()
->label('Settings')
->icon('heroicon-o-cog-6-tooth')
->collapsed(),
]);
}
本例中,我会传入了自定义的图标 icon()
,并使其中一个默认是折叠的 collapsed()
。
导航分组排序
使用 navigationGroups()
,你可以定义一个导航分组的新顺序。如果你只想渲染该分支而非定义整个 navigationGroup
对象,你可以以新排序将分组的标签传入:
$panel
->navigationGroups([
'Shop',
'Blog',
'Settings',
])
使导航分组不可折叠
默认情况下,导航分组是可折叠的。你可以通过调用 NavigationGroup
对象上的 collapsible(false)
可以禁用该行为:
use Filament\Navigation\NavigationGroup;
NavigationGroup::make()
->label('Settings')
->icon('heroicon-o-cog-6-tooth')
->collapsible(false);
或者,你也可以在配置中让所有的分组全局生效:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->collapsibleNavigationGroups(false);
}
将额外的 HTML 属性添加到导航分组
你可以将额外的 HTML 属性传递给导航组,导航组将合并到外部 DOM 元素上。将一个属性数组传递给 extraSidebarAttributes()
或 extraTopbarAttributes()
方法,其中键是属性名称,值是属性值:
NavigationGroup::make()
->extraSidebarAttributes(['class' => 'featured-sidebar-group']),
->extraTopbarAttributes(['class' => 'featured-topbar-group']),
extraSidebarAttributes()
将会被应用到侧边栏的导航组元素,而当使用顶部导航时, extraTopbarAttributes()
只应用到顶部导航栏组的下拉菜单中
在桌面端折叠侧边栏
要让桌面端的侧边栏像移动端一样可折叠,你可以使用配置:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->sidebarCollapsibleOnDesktop();
}
默认情况下,当你在桌面端折叠侧边栏时,导航图标仍会展示。你可以使用 sidebarFullyCollapsibleOnDesktop()
方法完全折叠侧边栏:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->sidebarFullyCollapsibleOnDesktop();
}
桌面端可折叠侧边栏的导航组
此章节只使用于
sidebarCollapsibleOnDesktop()
,而非sidebarFullyCollapsibleOnDesktop()
,因为完全折叠 UI 会隐藏整个侧边栏,而非修改器设计。
在桌面端使用可折叠侧边栏时,你也经常使用导航分组。默认情况下,每个导航分组的标签会在侧边栏折叠时隐藏,因为没有空间显示。即使导航分组本身是可折叠的,所有项目仍然在折叠的侧边栏中可见,因为没有分组标签可以点击打开分组。
该问题可以通过传入 icon()
图标得以解决,以达成最小化侧边 栏设计。定义图标后,该图标会在折叠的侧边栏中显示,而不再一直显示导航项。当点击图标时,会在图标旁边打开一个下拉菜单,显示分组中的导航项。
当传递图标给导航组时,即使导航项有图标,打开的侧边栏 UI 也不会显示导航项图标。这是为了使导航层次结构清晰,并使设计最小化。不过导航项的图标还是会在折叠后的侧边栏下拉菜单中显示,因为下拉菜单打开时,其层次结构就已经清晰明了。
注册自定义导航菜单项
你可以在配置中注册自定义导航菜单:
use Filament\Navigation\NavigationItem;
use Filament\Pages\Dashboard;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->navigationItems([
NavigationItem::make('Analytics')
->url('https://filament.pirsch.io', shouldOpenInNewTab: true)
->icon('heroicon-o-presentation-chart-line')
->group('Reports')
->sort(3),
NavigationItem::make('dashboard')
->label(fn (): string => __('filament-panels::pages/dashboard.title'))
->url(fn (): string => Dashboard::getUrl())
->isActiveWhen(fn () => request()->routeIs('filament.admin.pages.dashboard')),
// ...
]);
}
条件性隐藏导航菜单项
你也可以使用 visible()
或 hidden()
方法,传入条件,条件性隐藏导航项:
use Filament\Navigation\NavigationItem;
NavigationItem::make('Analytics')
->visible(auth()->user()->can('view-analytics'))
// or
->hidden(! auth()->user()->can('view-analytics')),
禁用资源或页面的导航菜单项
如果你要阻止你的资源或者页面在导航中显示,你可以使用:
protected static bool $shouldRegisterNavigation = false;
Or, you may override the shouldRegisterNavigation()
method:
public static function shouldRegisterNavigation(): bool
{
return false;
}
请注意这些方法不会控制直接访问资源或页面的权限。只会控制资源或页面是否在导航中展示。如果你也想控制权限,请通过资源授权或页面授权实现。
使用顶部导航
默认情况下,Filament 使用侧边栏导航。你可以在配置设置使用顶部导航:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->topNavigation();
}
导航自定义进阶
在配置中调用 navigation()
方法。允许你重写 Filament 自动生成的项目来创建一个自定义导航。该 API 是为了让你对导航有完全的控制权。
注册自定义导航项
调用 items()
方法,可以注册导航项目:
use App\Filament\Pages\Settings;
use App\Filament\Resources\UserResource;
use Filament\Navigation\NavigationBuilder;
use Filament\Navigation\NavigationItem;
use Filament\Pages\Dashboard;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->navigation(function (NavigationBuilder $builder): NavigationBuilder {
return $builder->items([
NavigationItem::make('Dashboard')
->icon('heroicon-o-home')
->isActiveWhen(fn (): bool => request()->routeIs('filament.pages.dashboard'))
->url(fn (): string => Dashboard::getUrl()),
...UserResource::getNavigationItems(),
...Settings::getNavigationItems(),
]);
});
}