Alternatively, you can use a full-page Livewire component:
use App\Livewire\ManagePost;use Illuminate\Support\Facades\Route;Route::get('posts/{post}/manage', ManagePost::class);
You must use the InteractsWithActions and InteractsWithSchemas traits, and implement the HasActions and HasSchemas interfaces on your Livewire component class:
use Filament\Actions\Concerns\InteractsWithActions;use Filament\Actions\Contracts\HasActions;use Filament\Schemas\Concerns\InteractsWithSchemas;use Filament\Schemas\Concerns\RestrictsFileUploadsToSchemaComponents;use Filament\Schemas\Contracts\HasSchemas;use Livewire\Component;class ManagePost extends Component implements HasActions, HasSchemas{ use InteractsWithActions; use InteractsWithSchemas; use RestrictsFileUploadsToSchemaComponents; // ...}
Add a method that returns your action. The method must share the exact same name as the action, or the name followed by Action:
use App\Models\Post;use Filament\Actions\Action;use Filament\Actions\Concerns\InteractsWithActions;use Filament\Actions\Contracts\HasActions;use Filament\Schemas\Concerns\InteractsWithSchemas;use Filament\Schemas\Concerns\RestrictsFileUploadsToSchemaComponents;use Filament\Schemas\Contracts\HasSchemas;use Livewire\Component;class ManagePost extends Component implements HasActions, HasSchemas{ use InteractsWithActions; use InteractsWithSchemas; use RestrictsFileUploadsToSchemaComponents; public Post $post; public function deleteAction(): Action { return Action::make('delete') ->color('danger') ->requiresConfirmation() ->action(fn () => $this->post->delete()); } // This method name also works, since the action name is `delete`: // public function delete(): Action // This method name does not work, since the action name is `delete`, not `deletePost`: // public function deletePost(): Action // ...}
$post is a model property on a regular Livewire component. Filament does not re-query or authorize it on later requests. Re-query and authorize the post before using it in the action, including any tenant or ownership restrictions your application requires. See Eloquent model restoration in Livewire for more information.
Finally, you need to render the action in your view. To do this, you can use {{ $this->deleteAction }}, where you replace deleteAction with the name of your action method:
You also need <x-filament-actions::modals /> which injects the HTML required to render action modals. This only needs to be included within the Livewire component once, regardless of how many actions you have for that component.
filament/actions also includes the following packages:
filament/forms
filament/infolists
filament/notifications
filament/support
These packages allow you to use their components within Livewire components.
For example, if your action uses Notifications, remember to include @livewire('notifications') in your layout and add @import '../../vendor/filament/notifications/resources/css/index.css' to your CSS file.If you are using any other Filament components in your action, make sure to install and integrate the corresponding package as well.
Sometimes, you may wish to pass arguments to your action. For example, if you’re rendering the same action multiple times in the same view, but each time for a different model, you could pass the model ID as an argument, and then retrieve it later. To do this, you can invoke the action in your view and pass in the arguments as an array:
Now, you can access the post ID in your action method:
use App\Models\Post;use Filament\Actions\Action;public function deleteAction(): Action{ return Action::make('delete') ->color('danger') ->requiresConfirmation() ->action(function (array $arguments) { $post = Post::find($arguments['post']); $post?->delete(); });}
Action arguments are client-controlled. Always query and authorize the requested record, including any tenant or ownership restrictions, before acting on it.
The hidden() and visible() methods also control if the action is disabled(), so they are still useful to protect the action from being run if the user does not have permission. Encapsulating this logic in the hidden() or visible() of the action itself is good practice otherwise you need to define the condition in the view and in disabled().You can also take advantage of this to hide any wrapping elements that may not need to be rendered if the action is hidden:
Now, when the first action is submitted, the second action will open in its place. The arguments that were originally passed to the first action get passed to the second action, so you can use them to persist data between requests.If the first action is canceled, the second one is not opened. If the second action is canceled, the first one has already run and cannot be cancelled.
Sometimes you may need to trigger an action without the user clicking on the built-in trigger button, especially from JavaScript. Here is an example action which could be registered on a Livewire component:
use Filament\Actions\Action;public function testAction(): Action{ return Action::make('test') ->requiresConfirmation() ->action(function (array $arguments) { dd('Test action called', $arguments); });}
You can trigger that action from a click in your HTML using the wire:click attribute, calling the mountAction() method and optionally passing in any arguments that you want to be available: