Table Builder
Actions
Getting started
Single actions
Single action buttons are rendered at the end of each table row.
If you're using the actions in a Livewire component, you can put them in the getTableActions()
method.
protected function getTableActions(): array{ return [ // ... ];}
If you're using them in admin panel resources or relation managers, you must put them on the $table
:
public static function table(Table $table): Table{ return $table ->actions([ // ... ]);}
Actions may be created using the static make()
method, passing its name. The name of the action should be unique. You can then pass a callback to action()
which executes the task, or a callback to url()
which generates a link URL:
If you would like the URL to open in a new tab, you can use the
openUrlInNewTab()
method.
use App\Models\Post;use Filament\Tables\Actions\Action; Action::make('edit') ->url(fn (Post $record): string => route('posts.edit', $record)) ->openUrlInNewTab()
Bulk actions
Bulk action buttons are visible when the user selects at least one record.
If you're using the actions in a Livewire component, you can put them in the getTableBulkActions()
method.
protected function getTableBulkActions(): array{ return [ // ... ];}
If you're using them in admin panel resources or relation managers, you must put them on the $table
:
public static function table(Table $table): Table{ return $table ->bulkActions([ // ... ]);}
Bulk actions may be created using the static make()
method, passing its name. The name of the action should be unique. You should then pass a callback to action()
which executes the task:
use Filament\Tables\Actions\BulkAction;use Illuminate\Database\Eloquent\Collection; BulkAction::make('delete') ->action(fn (Collection $records) => $records->each->delete())
Please note that Filament uses the parameter name
$records
in the function to inject the collection. Any other parameter name will resolve from the container instead.
You may deselect the records after a bulk action has been executed using the deselectRecordsAfterCompletion()
method:
use Filament\Tables\Actions\BulkAction;use Illuminate\Database\Eloquent\Collection; BulkAction::make('delete') ->action(fn (Collection $records) => $records->each->delete()) ->deselectRecordsAfterCompletion()
Setting a label
By default, the label of the action is generated from its name. You may customize this using the label()
method:
use App\Models\Post;use Filament\Tables\Actions\Action; Action::make('edit') ->label('Edit post') ->url(fn (Post $record): string => route('posts.edit', $record))
Optionally, you can have the label automatically translated by using the translateLabel()
method:
use App\Models\Post;use Filament\Tables\Actions\Action; Action::make('edit') ->translateLabel() // Equivalent to `label(__('Edit'))` ->url(fn (Post $record): string => route('posts.edit', $record))
Setting a color
Actions may have a color to indicate their significance. It may be either primary
, secondary
, success
, warning
or danger
:
use Filament\Tables\Actions\BulkAction;use Illuminate\Database\Eloquent\Collection; BulkAction::make('delete') ->action(fn (Collection $records) => $records->each->delete()) ->deselectRecordsAfterCompletion() ->color('danger')
Disabling record bulk actions
You may conditionally disable bulk actions for a specific record:
use Closure;use Illuminate\Database\Eloquent\Model; public function isTableRecordSelectable(): ?Closure{ return fn (Model $record): bool => $record->status === Status::Enabled;}
Setting a size
The default size for table actions is sm
but you may also change it to either md
or lg
:
use Filament\Tables\Actions\Action; Action::make('delete') ->size('lg')
Setting an icon
Bulk actions and some single actions may also render a Blade icon component to indicate their purpose:
use App\Models\Post;use Filament\Tables\Actions\Action;use Filament\Tables\Actions\BulkAction;use Illuminate\Database\Eloquent\Collection; BulkAction::make('delete') ->action(fn (Collection $records) => $records->each->delete()) ->deselectRecordsAfterCompletion() ->color('danger') ->icon('heroicon-o-trash') Action::make('edit') ->label('Edit post') ->url(fn (Post $record): string => route('posts.edit', $record)) ->icon('heroicon-s-pencil')
Modals
Actions and bulk actions may require additional confirmation or form information before they run. With the table builder, you may open a modal before an action is executed to do this.
Confirmation modals
You may require confirmation before an action is run using the requiresConfirmation()
method. This is useful for particularly destructive actions, such as those that delete records.
use Filament\Tables\Actions\BulkAction;use Illuminate\Database\Eloquent\Collection; BulkAction::make('delete') ->action(fn (Collection $records) => $records->each->delete()) ->deselectRecordsAfterCompletion() ->requiresConfirmation()
Note: The confirmation modal is not available when a
url()
is set instead of anaction()
. Instead, you should redirect to the URL within theaction()
callback.
Custom forms
You may also render a form in this modal to collect extra information from the user before the action runs.
You may use components from the Form Builder to create custom action modal forms. The data from the form is available in the $data
array of the action()
callback:
use App\Models\User;use Filament\Forms;use Filament\Tables\Actions\BulkAction;use Illuminate\Database\Eloquent\Collection; BulkAction::make('updateAuthor') ->action(function (Collection $records, array $data): void { foreach ($records as $record) { $record->author()->associate($data['authorId']); $record->save(); } }) ->form([ Forms\Components\Select::make('authorId') ->label('Author') ->options(User::query()->pluck('name', 'id')) ->required(), ])
Filling default data
You may fill the form with default data, using the mountUsing()
method:
use App\Models\User;use Filament\Forms;use Filament\Tables\Actions\Action;use Illuminate\Database\Eloquent\Collection; Action::make('updateAuthor') ->mountUsing(fn (Forms\ComponentContainer $form, User $record) => $form->fill([ 'authorId' => $record->author->id, ])) ->action(function (User $record, array $data): void { $record->author()->associate($data['authorId']); $record->save(); }) ->form([ Forms\Components\Select::make('authorId') ->label('Author') ->options(User::query()->pluck('name', 'id')) ->required(), ])
Wizards
You may easily transform action forms into multistep wizards.
On the action, simply pass in the wizard steps to the steps()
method, instead of form()
:
use Filament\Forms\Components\MarkdownEditor;use Filament\Forms\Components\TextInput;use Filament\Forms\Components\Toggle;use Filament\Forms\Components\Wizard\Step;use Filament\Tables\Actions\Action; Action::make('create') ->steps([ Step::make('Name') ->description('Give the category a clear and unique name') ->schema([ TextInput::make('name') ->required() ->reactive() ->afterStateUpdated(fn ($state, callable $set) => $set('slug', Str::slug($state))), TextInput::make('slug') ->disabled() ->required() ->unique(Category::class, 'slug', fn ($record) => $record), ]), Step::make('Description') ->description('Add some extra details') ->schema([ MarkdownEditor::make('description') ->columnSpan('full'), ]), Step::make('Visibility') ->description('Control who can view it') ->schema([ Toggle::make('is_visible') ->label('Visible to customers.') ->default(true), ]), ])
Setting a modal heading, subheading, and button label
You may customize the heading, subheading and button label of the modal:
use Filament\Tables\Actions\BulkAction;use Illuminate\Database\Eloquent\Collection; BulkAction::make('delete') ->action(fn (Collection $records) => $records->each->delete()) ->deselectRecordsAfterCompletion() ->requiresConfirmation() ->modalHeading('Delete posts') ->modalSubheading('Are you sure you\'d like to delete these posts? This cannot be undone.') ->modalButton('Yes, delete them')
Custom content
You may define custom content to be rendered inside your modal, which you can specify by passing a Blade view into the modalContent()
method:
use Filament\Tables\Actions\BulkAction; BulkAction::make('advance') ->action(fn () => $this->record->advance()) ->modalContent(view('filament.resources.event.actions.advance'))
By default, the custom content is displayed above the modal form if there is one, but you can add content below using modalFooter()
if you wish:
use Filament\Pages\Actions\BulkAction; BulkAction::make('advance') ->action(fn () => $this->record->advance()) ->modalFooter(view('filament.resources.event.actions.advance'))
Authorization
You may conditionally show or hide actions and bulk actions for certain users using either the visible()
or hidden()
methods, passing a closure:
use App\Models\Post;use Filament\Tables\Actions\Action; Action::make('edit') ->url(fn (Post $record): string => route('posts.edit', $record)) ->visible(fn (Post $record): bool => auth()->user()->can('update', $record))
This is useful for authorization of certain actions to only users who have permission.
Prebuilt actions
Replicate
This package includes an action to replicate table records. You may use it like so:
use Filament\Tables\Actions\ReplicateAction; ReplicateAction::make()
The excludeAttributes()
method is used to instruct the action which columns to be excluded from replication:
use Filament\Tables\Actions\ReplicateAction; ReplicateAction::make()->excludeAttributes(['slug'])
The beforeReplicaSaved()
method can be used to invoke a Closure before saving the replica:
use Filament\Tables\Actions\ReplicateAction;use Illuminate\Database\Eloquent\Model; ReplicateAction::make() ->beforeReplicaSaved(function (Model $replica): void { // ... })
The afterReplicaSaved()
method can be used to invoke a Closure after saving the replica:
use Filament\Tables\Actions\ReplicateAction;use Illuminate\Database\Eloquent\Model; ReplicateAction::make() ->afterReplicaSaved(function (Model $replica): void { // ... })
Retrieving user input
Just like normal actions, you can provide a form schema that can be used to modify the replication process:
use Filament\Tables\Actions\ReplicateAction; ReplicateAction::make() ->excludeAttributes(['title']) ->form([ TextInput::make('title')->required(), ]) ->beforeReplicaSaved(function (Model $replica, array $data): void { $replica->fill($data); })
Grouping
You may use an ActionGroup
object to group multiple table actions together in a dropdown:
use Filament\Tables; protected function getTableActions(): array{ return [ Tables\Actions\ActionGroup::make([ Tables\Actions\ViewAction::make(), Tables\Actions\EditAction::make(), Tables\Actions\DeleteAction::make(), ]), ];}
Position
By default, the row actions in your table are rendered in the final cell. You may change the position by overriding the getTableActionsPosition()
method:
use Filament\Tables\Actions\Position; protected function getTableActionsPosition(): ?string{ return Position::BeforeCells;}
Alignment
Row actions are aligned to the right in their cell by default. To change the alignment, update the configuration value inside of the package config:
'actions' => [ 'cell' => [ 'alignment' => 'right', // `right`, `left` or `center` ],]
Tooltips
If you want to use tooltips outside of the admin panel, make sure you have
@ryangjchandler/alpine-tooltip
installed in your app, includingtippy.css
. You'll also need to installtippy.css
if you're using a custom admin theme.
You may specify a tooltip to display when you hover over an action:
use Filament\Tables\Actions\Action; Action::make('edit') ->tooltip('Edit this blog post')
This method also accepts a closure that can access the current table record:
use Filament\Tables\Actions\Action;use Filament\Tables\Columns\TextColumn;use Illuminate\Database\Eloquent\Model; Action::make('edit') ->tooltip(fn (Model $record): string => "Edit {$record->title}")
Edit on GitHubStill need help? Join our Discord community or open a GitHub discussion