表格
布局
传统表格布局的问题
传统的表格因响应性差而臭名昭著。在移动端上,渲染水平方向较长的内容时,灵活性有限:
- 允许用户水平滚动以查看更多表格内容
- 在较小的设备上隐藏不重要的列
这两中在 Filament 中都能实现。当表溢出时,它们会自动水平滚动,你可以选择根据浏览器的响应断点显示和隐藏列。为此,你可以使用 visibleFrom()
或 hiddenFrom()
方法:
use Filament\Tables\Columns\TextColumn;
TextColumn::make('slug')
->visibleFrom('md')
这很好,但仍然存在一个明显的问题 —— 在移动设备上,用户如果不滚动,就无法一次看到表格行中的很多信息。
值得庆幸的是,Filament 允许你构建响应式类表格界面,而无需触碰 HTML 或 CSS。这些布局允许你在每个响应断点处准确定义内容在表行中的显示位置。


允许用户在移动端堆叠
我们来引入一个组件 - Split
:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
TextColumn::make('email'),
])


Split
组件用于包裹列字段,并允许它们在移动设备上堆叠。
默认情况下,Split
中的列将始终并排显示。但是你可以选择一个该行为开始(form()
)的响应式断点。在此之前,列将堆叠在一起:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
TextColumn::make('email'),
])->from('md')
本例中,这些列只有在 md
断点以上的设备中水平并排展示:


防止列创建空格
Split,就像表格列一样,会自动调整它们的空格,以确保每一列都有适当的分隔。你可以使用 grow(false)
来阻止这种情况发生。在这个例子中,我们将确保头像图片紧紧地贴在名称列上:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular()
->grow(false),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
TextColumn::make('email'),
])
允许 grow()
的其他列将进行调整以消耗新释放的空间:


Split 中堆叠
在 Split 中,你可以将多列垂直堆叠在一起。这允许你在桌面端中在更少列中显示更多数据:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
]),
])


在移动设备上隐藏堆叠
与单个列类似,你可以根据浏览器的响应式断点选择隐藏堆叠。为此,你可以使用 visibleFrom()
方法:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])->visibleFrom('md'),
])


对齐堆叠内容
默认情况下,堆叠中的列对齐到起始位置。你可以选择将堆叠中的列对齐到 Alignment::Center
或 Alignment::End
:
use Filament\Support\Enums\Alignment;
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone')
->grow(false),
TextColumn::make('email')
->icon('heroicon-m-envelope')
->grow(false),
])
->alignment(Alignment::End)
->visibleFrom('md'),
])
请确保堆栈内的列已设置 grow(false)
,否则它们将拉伸以填充堆栈的整个宽度并遵循它们自己的对齐配置而不是堆栈的对齐配置。

堆叠内容的间距
默认情况下,堆叠内容在列之间没有垂直 padding。要添加 padding,你可以使用 space()
方法,该方法接受 1
、2
或 3
,对应于 Tailwind 的间距比例:
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\TextColumn;
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])->space(1)
使用网格控制列宽
有时,当列字段包含很多内容时,使用 Split
会出现不一致的宽度。这是因为它内部是使用 Flexbox 驱动,并且每行独自控制分配多少空格给内容。
作为替代方案,你可以使用 Grid
布局,它使用 CSS 网格布局,允许你控制列宽:
use Filament\Tables\Columns\Layout\Grid;
use Filament\Tables\Columns\TextColumn;
Grid::make([
'lg' => 2,
])
->schema([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])
从 lg
断点开始,这些列字段在网格内始终会消费同样的宽度。
你也可以在其他断点处自定义网格的列数:
use Filament\Tables\Columns\Layout\Grid;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\TextColumn;
Grid::make([
'lg' => 2,
'2xl' => 4,
])
->schema([
Stack::make([
TextColumn::make('name'),
TextColumn::make('job'),
]),
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])
你甚至可以控制每个组件在每个临界点所使用的网格列数:
use Filament\Tables\Columns\Layout\Grid;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\TextColumn;
Grid::make([
'lg' => 2,
'2xl' => 5,
])
->schema([
Stack::make([
TextColumn::make('name'),
TextColumn::make('job'),
])->columnSpan([
'lg' => 'full',
'2xl' => 2,
]),
TextColumn::make('phone')
->icon('heroicon-m-phone')
->columnSpan([
'2xl' => 2,
]),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])
可折叠内容
当你使用像 Split 或 Stack 这样的列布局时,你也可以添加可折叠的内容。当你不想一次性显示表中的所有数据,但仍然希望用户在需要访问时可以访问它,而无需调出当前页面时,这非常有用。
Split 和 Stack 组件可以设置为 collapsible()
,同时还有一个专门的 Panel
组件,它提供了一个预设的背景颜色和边框半径,将可折叠内容与其他内容分开:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Panel;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
[
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
]),
Panel::make([
Stack::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
]),
])->collapsible(),
]
使用 collapsed(false)
方法,你可以让面板默认展开:
use Filament\Tables\Columns\Layout\Panel;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\TextColumn;
Panel::make([
Split::make([
TextColumn::make('phone')
->icon('heroicon-m-phone'),
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])->from('md'),
])->collapsed(false)


将记录排列到网格中
有时,你可能会发现你的数据更适合使用网格布局,而不是列表。Filament 也可以处理这种情况!
只需使用 $table->contentGrid()
方法:
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->columns([
Stack::make([
// Columns
]),
])
->contentGrid([
'md' => 2,
'xl' => 3,
]);
}
本例中,这些行将会在网格中展示:
这些设置完全是可自定义的,从 sm
到 2xl
的任何临界点都能包含 1
到 12
列。


自定义 HTML
使用 View
组件,你可以将自定义 HTML 添加到你的表格中。它也可以设置成可折叠 collapsible()
:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\View;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
[
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
]),
View::make('users.table.collapsible-row-content')
->collapsible(),
]
然后,新建一个 /resources/views/users/table/collapsible-row-content.blade.php
文件,并添加 HTML。你可以使用 $getRecord()
访问表中的记录:
<p class="px-4 py-3 bg-gray-100 rounded-lg">
<span class="font-medium">
Email address:
</span>
<span>
{{ $getRecord()->email }}
</span>
</p>
嵌入其他组件
你甚至可以将列或者其他布局组件传入到 components()
方法:
use Filament\Support\Enums\FontWeight;
use Filament\Tables\Columns\Layout\Split;
use Filament\Tables\Columns\Layout\View;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
[
Split::make([
ImageColumn::make('avatar')
->circular(),
TextColumn::make('name')
->weight(FontWeight::Bold)
->searchable()
->sortable(),
]),
View::make('users.table.collapsible-row-content')
->components([
TextColumn::make('email')
->icon('heroicon-m-envelope'),
])
->collapsible(),
]
然后,在 Blade 文件中渲染组件:
<div class="px-4 py-3 bg-gray-100 rounded-lg">
@foreach ($getComponents() as $layoutComponent)
{{ $layoutComponent
->record($getRecord())
->recordKey($getRecordKey())
->rowLoop($getRowLoop())
->renderInLayout() }}
@endforeach
</div>
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion