默认情况下,Filament 将为你的每个资源、自定义页面和集群注册导航项。这些类包含你可以覆盖的静态属性和方法,以配置该导航项。
如果您希望为您的应用添加第二层导航,您可以使用集群。它们对于将资源和页面组合在一起非常有用。
默认情况下,导航标签是从资源或页面的名称生成的。您可以使用 $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 属性为导航栏 图标 指定一个仅用于激活项的图标:
use BackedEnum;
protected static string | BackedEnum | null $activeNavigationIcon = 'heroicon-o-document-text';默认情况下,导航项按字母顺序排序。您可以使用 $navigationSort 属性自定义此设置:
protected static ?int $navigationSort = 3;现在,排序值较低的导航项将出现在排序值较高的导航项之前 - 排序顺序为升序。
要在导航项旁边添加徽章,您可以使用 getNavigationBadge() 方法并返回徽章的内容:
public static function getNavigationBadge(): ?string
{
return static::getModel()::count();
}
如果 getNavigationBadge() 返回徽章值,它将默认使用主题色显示。要根据上下文设置徽章样式,请从 getNavigationBadgeColor() 方法返回 danger, gray, info, primary, success 或 warning:
public static function getNavigationBadgeColor(): ?string
{
return static::getModel()::count() > 10 ? 'warning' : 'primary';
}
导航徽章的自定义工具提示可以在$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';
同一导航组中的所有项目将一起显示在同一组标签下,本例中为“设置”。未分组的项目将保留在导航的开头。
您可以将导航项作为其他项的子项进行分组,通过传递父项的标签作为 $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');
}如上所示,如果父项具有导航组,则该导航组也必须定义,以便可以识别正确的父项。
如果你正在使用这样的第三级导航,你应该考虑改用集群,它们是资源和自定义页面的逻辑分组,可以拥有自己独立的导航。
您可以自定义导航组,通过在 配置 中调用 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 属性给导航组,它们将合并到外部 DOM 元素上。 传递一个属性数组给 extraSidebarAttributes() 或 extraTopbarAttributes() 方法,其中键是属性名,值是属性值:
NavigationGroup::make()
->extraSidebarAttributes(['class' => 'featured-sidebar-group']),
->extraTopbarAttributes(['class' => 'featured-topbar-group']),该 extraSidebarAttributes() 将应用于包含在侧边栏中的导航组元素,而该 extraTopbarAttributes() 将仅应用于顶栏导航组下拉菜单在使用 顶部导航 时。
您可以使用枚举类来注册导航组,这使您可以在一个地方控制它们的标签、图标和顺序,而无需在配置中注册它们。
为此,您可以创建一个枚举类,其中为每个组定义了案例:
enum NavigationGroup
{
case Shop;
case Blog;
case Settings;
}定义案例的顺序将控制导航组的顺序。
要为资源或自定义页面使用枚举导航组,你可以将 $navigationGroup 属性设置为枚举成员:
protected static string | UnitEnum | null $navigationGroup = NavigationGroup::Shop;你也可以在枚举类上实现 HasLabel 接口,为每个组定义自定义标签:
use Filament\Support\Contracts\HasLabel;
enum NavigationGroup implements HasLabel
{
case Shop;
case Blog;
case Settings;
public function getLabel(): string
{
return match ($this) {
self::Shop => __('navigation-groups.shop'),
self::Blog => __('navigation-groups.blog'),
self::Settings => __('navigation-groups.settings'),
};
}
}你也可以在枚举类上实现 HasIcon 接口,以定义每个组的自定义图标:
use Filament\Support\Contracts\HasIcon;
enum NavigationGroup implements HasIcon
{
case Shop;
case Blog;
case Settings;
public function getIcon(): ?string
{
return match ($this) {
self::Shop => 'heroicon-o-shopping-cart',
self::Blog => 'heroicon-o-pencil',
self::Settings => 'heroicon-o-cog-6-tooth',
};
}
}为了让侧边栏在桌面端和移动端都可折叠,你可以使用配置:
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(),因为完全可折叠的用户界面只是隐藏了整个侧边栏,而不是改变其设计。
在桌面端使用可折叠侧边栏时,你也经常会用到导航组。默认情况下,当侧边栏折叠时,每个导航组的标签都会被隐藏,因为没有空间显示它们。即使导航组本身是可折叠的,所有项目仍会在折叠的侧边栏中可见,因为没有可点击展开导航组的组标签。
这些问题可以通过向导航组对象传递一个icon()来解决,以实现非常简洁的侧边栏设计。当定义了图标时,该图标将始终显示在折叠的侧边栏中,而不是项目。点击图标时,一个下拉菜单将在图标旁边打开,显示组中的项目。
当给导航组传递一个图标时,即使其项目也有图标,展开的侧边栏用户界面也不会显示项目图标。这是为了保持导航层级清晰,并使设计简洁。然而,项目图标会在折叠侧边栏的下拉菜单中显示,因为下拉菜单已打开的事实已经清楚地表明了层级关系。
要注册新的导航项,您可以使用配置:
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);
}
您可以通过向 topbar() 方法传递 false 来完全禁用顶栏:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->topbar(false);
}您可以完全替换用于渲染侧边栏和顶栏的 Livewire 组件,将您自己的 Livewire 组件类名传入 sidebarLivewireComponent() 或 topbarLivewireComponent() 方法中:
use App\Livewire\Sidebar;
use App\Livewire\Topbar;
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->sidebarLivewireComponent(Sidebar::class)
->topbarLivewireComponent(Topbar::class);
}默认布局将显示面包屑,以指示当前页面在应用层级结构中的位置。
你可以在你的配置中禁用面包屑:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
// ...
->breadcrumbs(false);
}面板中的页面加载后,侧边栏和顶部栏不会重新加载,直到您离开当前页面,或点击菜单项触发操作。您可以通过分派 refresh-sidebar 或 refresh-topbar 浏览器事件,手动重新加载这些组件以更新它们。
要从 PHP 调度事件,您可以从任何 Livewire 组件中调用 $this->dispatch() 方法,例如页面类、关系管理器类或小组件类:
$this->dispatch('refresh-sidebar');当你的代码不在 Livewire 组件内部时,例如当你有一个自定义的动作类时,你可以将 $livewire 参数注入到一个闭包函数中,并调用它的 dispatch() 方法:
use Filament\Actions\Action;
use Livewire\Component;
Action::make('create')
->action(function (Component $livewire) {
// ...
$livewire->dispatch('refresh-sidebar');
})或者,你可以从 JavaScript 派发一个事件,使用 $dispatch() Alpine.js 辅助方法,或者原生的浏览器 window.dispatchEvent() 方法:
<button x-on:click="$dispatch('refresh-sidebar')" type="button">
Refresh Sidebar
</button>window.dispatchEvent(new CustomEvent('refresh-sidebar'));