表格
Actions
简介
Filament 表格可以使用 Action。Action 是添加到表格行末或表格头部或者 toolbar 上的按钮。比如,如果你想在表格头部添加”新建”记录的 Action,在每行中添加”编辑”和”删除” Action。批量 Action可以在记录选中时执行代码。另外,Action 也可以添加到表格列,这样该列中的每个单元格都是 action 的触发器。
强烈建议阅读自定义 Action 触发按钮 和 Action 模态框文档,去了解 Action 的全部功能。
记录 Action
Action 按钮可以渲染在每个表格行的末尾。你可以将其放到 $table->recordActions()
方法中:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->recordActions([
// ...
]);
}
Action 可以使用静态的 make()
方法,传入唯一名称创建。
然后你可以传入函数到 action()
中执行任务,或者传入函数到 url()
中创建链接:
use App\Models\Post;
use Filament\Actions\Action;
Action::make('edit')
->url(fn (Post $record): string => route('posts.edit', $record))
->openUrlInNewTab()
Action::make('delete')
->requiresConfirmation()
->action(fn (Post $record) => $record->delete())
All methods on the action accept callback functions, where you can access the current table $record
that was clicked.

Positioning record actions before columns
By default, the record actions in your table are rendered in the final cell of each row. You may move them before the columns by using the position
argument:
use Filament\Tables\Enums\RecordActionsPosition;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->recordActions([
// ...
], position: RecordActionsPosition::BeforeColumns);
}

Positioning record actions before the checkbox column
By default, the record actions in your table are rendered in the final cell of each row. You may move them before the checkbox column by using the position
argument:
use Filament\Tables\Enums\RecordActionsPosition;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->recordActions([
// ...
], position: RecordActionsPosition::BeforeCells);
}

访问选中的表格行
你可能希望某个操作能够访问表中所有选定的行。通常,这可以通过表头中的批量操作来实现。不过,你可能希望使用行操作来实现,其中选定的行会为该操作提供上下文。
例如,你可能希望有一个行操作将行数据复制到所有选定的记录。即使没有定义批量操作,要强制表可选,也需要使用 selectable()
方法。要允许操作访问选定的记录,你需要使用 accessSelectedRecords()
方法。然后,你可以在操作中使用 $selectedRecords
参数来访问选定的记录:
use Filament\Actions\Action;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
public function table(Table $table): Table
{
return $table
->selectable()
->recordActions([
Action::make('copyToSelected')
->accessSelectedRecords()
->action(function (Model $record, Collection $selectedRecords) {
$selectedRecords->each(
fn (Model $selectedRecord) => $selectedRecord->update([
'is_active' => $record->is_active,
]),
);
}),
]);
}
批量操作
表格也支持“批量操作”。当用户选择表格中的行时,可以使用这些操作。通常,选择行时会显示一个“批量操作”按钮。用户点击此按钮后,会显示一个下拉菜单,其中包含可供选择的操作。你可以将这些操作放入 $table->toolbarActions()
或 $table->headerActions()
方法中:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->toolbarActions([
// ...
]);
}
批量操作使用静态的 make()
方法,并传入其唯一名称创建。然后,你可以传入一个回调函数到 action()
中,使之执行任务:
use Filament\Actions\BulkAction;
use Illuminate\Database\Eloquent\Collection;
BulkAction::make('delete')
->requiresConfirmation()
->action(fn (Collection $records) => $records->each->delete())
该函数允许你访问当前表格选中的 $records
。它是模型的 Eloquent 集合。

授权批量操作
使用批量操作时,你可以检查所选每条记录的策略方法。这对于检查用户是否有权对每条记录执行相应操作非常有用。你可以使用 authorizeIndividualRecords()
方法,并传递策略方法的名称,该方法将针对每条记录调用。如果策略拒绝授权,则该记录将不会出现在批量操作的 $records
参数中:
use Filament\Actions\BulkAction;
use Illuminate\Database\Eloquent\Collection;
BulkAction::make('delete')
->requiresConfirmation()
->authorizeIndividualRecords('delete')
->action(fn (Collection $records) => $records->each->delete())
批量操作通知
批量操作完成后,你可能希望向用户发送一条通知,其中包含操作成功的摘要。如果你对单个记录使用授权,则此功能尤其有用,因为用户可能不知道实际影响了多少条记录。
要在批量操作完成后发送通知,你应该设置 successNotificationTitle()
和 failureNotificationTitle()
:
- 当所有记录均已成功处理时,
successNotificationTitle()
将用作通知的标题。 - 当部分或全部记录处理失败时,
failureNotificationTitle()
将用作通知的标题。通过将函数传递给此方法,你可以注入$successCount
和$failureCount
参数,以将此信息提供给用户。
比如:
use Filament\Actions\BulkAction;
use Illuminate\Database\Eloquent\Collection;
BulkAction::make('delete')
->requiresConfirmation()
->authorizeIndividualRecords('delete')
->action(fn (Collection $records) => $records->each->delete())
->successNotificationTitle('Deleted users')
->failureNotificationTitle(function (int $successCount, int $totalCount): string {
if ($successCount) {
return "{$successCount} of {$totalCount} users deleted";
}
return 'Failed to delete any users';
})
You can also use a special authorization response object in a policy method to provide a custom message about why the authorization failed. The special object is called DenyResponse
and replaces Response::deny()
, allowing the developer to pass a function as the message which can receive information about how many records were denied by that authorization check:
use App\Models\User;
use Filament\Support\Authorization\DenyResponse;
use Illuminate\Auth\Access\Response;
class UserPolicy
{
public function delete(User $user, User $model): bool | Response
{
if (! $model->is_admin) {
return true;
}
return DenyResponse::make('cannot_delete_admin', message: function (int $failureCount, int $totalCount): string {
if (($failureCount === 1) && ($totalCount === 1)) {
return 'You cannot delete an admin user.';
}
if ($failureCount === $totalCount) {
return 'All users selected were admin users.';
}
if ($failureCount === 1) {
return 'One of the selected users was an admin user.';
}
return "{$failureCount} of the selected users were admin users.";
});
}
}
The first argument to the make()
method is a unique key to identify that failure type. If multiple failures of that key are detected, they are grouped together and only one message is generated. If there are multiple points of failure in the policy method, each response object can have its own key, and the messages will be concatenated together in the notification.
报告批量操作处理中的失败
Alongside individual record authorization messages, you can also report failures in the bulk action processing itself. This is useful if you want to provide a message for each record that failed to be processed for a particular reason, even after authorization passes. This is done by injecting the Action
instance into the action()
function, and calling the reportBulkProcessingFailure()
method on it, passing a key and message function similar to DenyResponse
:
use Filament\Actions\BulkAction;
use Illuminate\Database\Eloquent\Collection;
BulkAction::make('delete')
->requiresConfirmation()
->authorizeIndividualRecords('delete')
->action(function (BulkAction $action, Collection $records) {
$records->each(function (Model $record) use ($action) {
$record->delete() || $action->reportBulkProcessingFailure(
'deletion_failed',
message: function (int $failureCount, int $totalCount): string {
if (($failureCount === 1) && ($totalCount === 1)) {
return 'One user failed to delete.';
}
if ($failureCount === $totalCount) {
return 'All users failed to delete.';
}
if ($failureCount === 1) {
return 'One of the selected users failed to delete.';
}
return "{$failureCount} of the selected users failed to delete.";
},
);
});
})
->successNotificationTitle('Deleted users')
->failureNotificationTitle(function (int $successCount, int $totalCount): string {
if ($successCount) {
return "{$successCount} of {$totalCount} users deleted";
}
return 'Failed to delete any users';
})
The delete()
method on an Eloquent model returns false
if the deletion fails, so you can use that to determine if the record was deleted successfully. The reportBulkProcessingFailure()
method will then add a failure message to the notification, which will be displayed when the action is completed.
The reportBulkProcessingFailure()
method can be called at multiple points during the action execution for different reasons, but you should only call it once per record. You should not proceed with the action for that particular record once you have called the method for it.
批量操作分组
You may use a BulkActionGroup
object to group multiple bulk actions together in a dropdown. Any bulk actions that remain outside the BulkActionGroup
will be rendered next to the dropdown’s trigger button:
use Filament\Actions\BulkAction;
use Filament\Actions\BulkActionGroup;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->toolbarActions([
BulkActionGroup::make([
BulkAction::make('delete')
->requiresConfirmation()
->action(fn (Collection $records) => $records->each->delete()),
BulkAction::make('forceDelete')
->requiresConfirmation()
->action(fn (Collection $records) => $records->each->forceDelete()),
]),
BulkAction::make('export')->button()->action(fn (Collection $records) => ...),
]);
}
Alternatively, if all of your bulk actions are grouped, you can use the shorthand groupedBulkActions()
method:
use Filament\Actions\BulkAction;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->groupedBulkActions([
BulkAction::make('delete')
->requiresConfirmation()
->action(fn (Collection $records) => $records->each->delete()),
BulkAction::make('forceDelete')
->requiresConfirmation()
->action(fn (Collection $records) => $records->each->forceDelete()),
]);
}
批量操作完成后取消选择
使用 deselectRecordsAfterCompletion()
方法,你可以在批量操作执行后取消记录选择:
use Filament\Actions\BulkAction;
use Illuminate\Database\Eloquent\Collection;
BulkAction::make('delete')
->action(fn (Collection $records) => $records->each->delete())
->deselectRecordsAfterCompletion()
禁用某些行的批量操作
你可以条件性地禁用指定的记录的批量操作:
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
public function table(Table $table): Table
{
return $table
->toolbarActions([
// ...
])
->checkIfRecordIsSelectableUsing(
fn (Model $record): bool => $record->status === Status::Enabled,
);
}
阻止批量选择所有页面
selectCurrentPageOnly()
可用于阻止用户一次性批量选择表格中的所有记录,而是只允许一次选择一个页面:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->toolbarActions([
// ...
])
->selectCurrentPageOnly();
}
改进批量操作性能
默认情况下,批量操作将会在将记录传入到 action()
函数前,将所有 Eloquent 记录都加载到内存中。
如果你处理的是大体量记录,你可以使用 chunkSelectedRecords()
方法,一次只获取少量数据。这将能减少应用的内存消耗:
use Filament\Actions\BulkAction;
use Illuminate\Support\LazyCollection;
BulkAction::make()
->chunkSelectedRecords(250)
->action(function (LazyCollection $records) {
// Process the records...
})
你仍然可以像平时一样循环迭代 $records
集合,不过,该集合将会是 LazyCollection
而非通常的集合。
You can also prevent Filament from fetching the Eloquent models in the first place, and instead just pass the IDs of the selected records to the action()
function. This is useful if you are processing a large number of records, and you don’t need to load them into memory:
use Filament\Actions\BulkAction;
use Illuminate\Support\Collection;
BulkAction::make()
->fetchSelectedRecords(false)
->action(function (Collection $records) {
// Process the records...
})
Header actions
Both actions and bulk actions can be rendered in the header of the table. You can put them in the $table->headerActions()
method:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->headerActions([
// ...
]);
}
This is useful for things like “create” actions, which are not related to any specific table row, or bulk actions that need to be more visible.

Toolbar actions
Both actions and bulk actions can be rendered in the toolbar of the table. You can put them in the $table->toolbarActions()
method:
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->toolbarActions([
// ...
]);
}
This is useful for things like “create” actions, which are not related to any specific table row, or bulk actions that need to be more visible.

Column actions
Actions can be added to columns, such that when a cell in that column is clicked, it acts as the trigger for an action. You can learn more about column actions in the documentation.
Action 分组
你可以使用 ActionGroup
对象,在下拉菜单中将多个表格 Action 分组到一起:
use Filament\Actions\ActionGroup;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Tables\Table;
public function table(Table $table): Table
{
return $table
->recordActions([
ActionGroup::make([
ViewAction::make(),
EditAction::make(),
DeleteAction::make(),
]),
// ...
]);
}
你可以在 Action 文档中查看更多自定义 Action 分组的信息。

Still need help? Join our Discord community or open a GitHub discussion