导航栏
概述
简介
默认情况下,Filament 将为每个资源、自定义页面 和 Clusters 注册导航项目。这些类都包含一些静态属性和方法,你可以重写配置导航项目。
如果你想在应道的导航中添加第二层导航,可以使用 Clusters。这对于将资源和页面分组到一起很有用。
自定义导航项标签
默认情况下,导航标签是由资源或者页面名称生成。你可以使用 $navigationLabel 属性自定义:
protected static ?string $navigationLabel = 'Custom Navigation Label';
此外,你也可以自定义 getNavigationLabel() 方法:
public static function getNavigationLabel(): string
{
return 'Custom Navigation Label';
}
自定义导航项图标
要自定义导航项的图标,你可以重写资源或页面类的 $navigationIcon 属性:
use BackedEnum;
protected static string | BackedEnum | null $navigationIcon = 'heroicon-o-document-text';
如果你将同一导航分组内的所有项目都设置 $navigationIcon = null,则这些项目将通过分组标签下方的垂直条连接起来。
当导航项激活时切换图标
通过 $activeNavigationIcon 属性,你指定一个仅用于导航项激活时的图标:
protected static ?string $activeNavigationIcon = 'heroicon-o-document-text';
导航项排序
默认情况下,导航项按照字母顺序排序。你可以使用 $navigationSort 属性自定义排序:
protected static ?int $navigationSort = 3;
排序值较低的导航项会排在排序值高的项目之前,排序顺序为升序。
添加徽章到导航项中
要在导航项旁添加徽章,你可以使用 getNavigationBadge() 方法并返回徽章内容:
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';
}
导航项分组
通过指定资源和自定义页面中的 $navigationGroup 属性,你可以对导航项进行分组:
use UnitEnum;
protected static string | UnitEnum | null $navigationGroup = 'Settings';
处于同一个分组的项目将会展示在同一个分组标签之下,比如上例中的 Settings。未分组项将保留在导航的起始位置。.
在其他项目之下分组导航项
将父项标签传入到 $navigationParentItem 中,你可以将导航项作为其他项目的子项:
use UnitEnum;
protected static ?string $navigationParentItem = 'Notifications';
protected static string | UnitEnum | null $navigationGroup = 'Settings';
你也可以使用 getNavigationParentItem() 动态设置父项标签:
public static function getNavigationParentItem(): ?string
{
return __('filament/navigation.groups.settings.items.notifications');
}
如上所示,如果父项有导航分组,就必须定义导航分组,这样磁能正确识别父项。
TIP
如果你寻找类似的第三级导航分组,则可以考虑 Clusters,它是资源和自定义页面的逻辑分组,可以共享自己的单独导航。
自定义导航分组
在配置中调用 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(fn (): string => __('navigation.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();
}
桌面端可折叠侧边栏导航分组
NOTE
本章节仅适用于 sidebarCollapsibleOnDesktop(),不包括 sidebarFullyCollapsibleOnDesktop()。因为可全折叠 UI 会隐藏整个侧边栏而不只是修改其外观。
当在桌面端使用可折叠侧边栏时,你常常也会使用导航分组。默认情况下,每个导航分组的标签会在侧边栏折叠后隐藏,因为没有空间展示。即使导航分组是可折叠的,所有项目在折叠的侧边栏中仍然可见,因为没有分组标签可用于展开分组。
这个情况可以通过传入一个 icon() 到导航分组对象中来解决。该图标(而非导航项)将会始终显示在折叠后的侧边栏中。当点击该图标时,会在图标旁边打开下拉菜单,显示分组中的项目。
当传入图标到导航分组中时,即使这些项目有图标,展开的侧边栏 UI 也不会显示项目图标。这是为了使导航层次分明,以及设计最小化。不过,项目图标会显示在折叠后的侧边栏下拉菜单中,因为下拉菜单的打开已经使得层次事实上清晰明了了。
注册自定义导航项
要注册心的导航项,你可以使用面板配置:
use Filament\Navigation\NavigationItem;
use Filament\Pages\Dashboard;
use Filament\Panel;
use function Filament\Support\original_request;
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 () => original_request()->routeIs('filament.admin.pages.dashboard')),
// ...
]);
}
根据情况隐藏导航项
使用 visible() 或 hidden() 方法,传入要检查的条件,你可以根据情况隐藏导航项:
use Filament\Navigation\NavigationItem;
NavigationItem::make('Analytics')
->visible(fn(): bool => auth()->user()->can('view-analytics'))
// or
->hidden(fn(): bool => ! auth()->user()->can('view-analytics')),
禁用资源或者页面导航项
要阻止资源或者页面在导航中显示,你可以使用:
protected static bool $shouldRegisterNavigation = false;
或者,你也可以重写 shouldRegisterNavigation() 方法:
public static function shouldRegisterNavigation(): bool
{
return false;
}
请注意,这些方法不会直接访问资源或页面。它们只是控制资源或页面是否显示在导航中。如果你也想控制访问权限,请使用资源授权或者页面授权。
使用顶部导航
默认情况下,Filament 使用侧边栏导航。你可以在配置中将其转换成使用顶部导航:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->topNavigation();
}
自定义侧边栏宽度
你可以在配置中将宽度传入到 sidebarWidth() 方法中,自定义侧边栏的宽度:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->sidebarWidth('40rem');
}
此外,如果使用了 sidebarCollapsibleOnDesktop() 方法,你可以在配置中使用 collapsedSidebarWidth() 方法自定义折叠后图标的宽度:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->sidebarCollapsibleOnDesktop()
->collapsedSidebarWidth('9rem');
}
高级导航自定义
navigation() 方法可以在配置中调用。它允许你构建自定义导航,以覆盖 Filament 自动生成的导航项。此 API 旨在让你完全控制导航。
注册自定义导航项
要注册导航项,请调用 items() 方法:
use App\Filament\Pages\Settings;
use App\Filament\Resources\Users\UserResource;
use Filament\Navigation\NavigationBuilder;
use Filament\Navigation\NavigationItem;
use Filament\Pages\Dashboard;
use Filament\Panel;
use function Filament\Support\original_request;
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 => original_request()->routeIs('filament.admin.pages.dashboard'))
->url(fn (): string => Dashboard::getUrl()),
...UserResource::getNavigationItems(),
...Settings::getNavigationItems(),
]);
});
}
注册自定义导航分组
如果你项注册分组,你可以调用 groups() 方法:
use App\Filament\Pages\HomePageSettings;
use App\Filament\Resources\Categories\CategoryResource;
use App\Filament\Resources\Pages\PageResource;
use Filament\Navigation\NavigationBuilder;
use Filament\Navigation\NavigationGroup;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->navigation(function (NavigationBuilder $builder): NavigationBuilder {
return $builder->groups([
NavigationGroup::make('Website')
->items([
...PageResource::getNavigationItems(),
...CategoryResource::getNavigationItems(),
...HomePageSettings::getNavigationItems(),
]),
]);
});
}
禁用导航
通过将 false 传递给 navigation() 方法,你可以完全禁用导航栏:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->navigation(false);
}
禁用顶部栏
通过将 false 传递给 topbar() 方法,你可以完全禁用顶部栏:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->topbar(false);
}
禁用面包屑
默认布局将显示面包屑导航,以指示当前页面在应用层次结构中的位置。
你可以在配置中禁用面包屑导航:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->breadcrumbs(false);
}
重新加载侧边栏和顶部导航栏
当面板中的页面被加载时,侧边栏和顶部导航栏都不会重载,除非离开该页面或者点击菜单项去触发 Action。通过派发 refresh-sidebar 或 refresh-topbar 浏览器事件,你可以手动重载这些组件。
要使用 PHP 派发事件,你可以在任何 Livewire 组件(比如页面类,关联管理器类或者 Widget 类中)中调用 $this->dispatch() 方法:
$this->dispatch('refresh-sidebar');
如果代码不在某个 Livewire 组件中,比如在你自定义的 Action 类中, 你可以注入 $livewire 参数到闭包函数中,并在其上调用 dispatch():
use Filament\Actions\Action;
use Livewire\Component;
Action::make('create')
->action(function (Component $livewire) {
// ...
$livewire->dispatch('refresh-sidebar');
})
此外,使用 $dispatch() Alpine.js 辅助方法,或者浏览器原生的 window.dispatchEvent() 方法,你可以使用 JavaScript 派发事件,
<button x-on:click="$dispatch('refresh-sidebar')" type="button">
Refresh Sidebar
</button>
window.dispatchEvent(new CustomEvent('refresh-sidebar'));
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion