- Published on
How to open a modal form from your top navigation in Filament
- Authors
-
-
- Name
- Cristian Iosif
- Laravel and FilamentPHP Enthusiast
- X.com
- @X
-
While working on a small project, I needed to add a quick way to create a record from anywhere, so the perfect place for this was the top navigation menu. In this article, I will try to explain how I implemented this feature in Filament.
We will not create a record now, but let's say you want your users to have a quick way to report an issue on your application. Of course, you would be able to create a record if that's what you need, but for now, let's stick to the issue reporting feature.
First of all, we need to create a new Livewire component that will be responsible for opening the modal and submitting the form. Let's call this component ReportIssue
...
1php artisan make:livewire ReportIssue
...and that's what we get from the command above:
1<?php 2 3namespace App\Livewire; 4 5use Livewire\Component; 6 7class ReportIssue extends Component 8{ 9 public function render()10 {11 return view('livewire.report-issue');12 }13}
Well, nothing new, I'm sure! Now, let's hook some Filament magic 🪄 into this component. We will use the HasForms
and HasActions
interfaces and add the necessary methods stubs using these traits InteractsWithForm
and InteractsWithActions
. Here is the updated component:
1class ReportIssue extends Component implements HasForms, HasActions 2{ 3 use InteractsWithActions; 4 use InteractsWithForms; 5 6 public function render() 7 { 8 return view('livewire.report-issue'); 9 }10}
If we now have access to Filament, let's create a new action called openReportIssueModal
:
1use Filament\Actions\Action; 2//... 3 4class ReportIssue extends Component implements HasForms, HasActions 5{ 6 //... 7 8 public function openReportIssueModal(): Action 9 {10 return Action::make('issues')11 ->label('Report an issue')12 ->modalIcon('heroicon-o-exclamation-triangle')13 ->modalHeading(__('Report an issue'))14 ->modalDescription(__('If you encountered an issue, please report it!'));15 }16}
But, this does nothing without a view ... Let's use the view that was created when we ran the php artisan make:livewire
command and add the following code:
1<div>2 {{ $this->openReportIssueModal }}3 4 <x-filament-actions::modals />5</div>
Well, it seems we're almost there! But, the trick is how we tell Filament to use our new button and to add it to the top navigation menu. We will use the Filament Render Hooks to do the trick. Open your AdminPanelProvider
(or whatever Filament PanelProvider you would like to add this behavior to) and add the following code:
1use Filament\View\PanelsRenderHook; 2//... 3 4class AdminPanelProvider extends PanelProvider 5{ 6 public function panel(Panel $panel): Panel 7 { 8 return $panel 9 //...10 ->renderHook(11 PanelsRenderHook::GLOBAL_SEARCH_AFTER,12 fn (): string => Blade::render('@livewire(\'report-issue\')'),13 )14 //...15 }16}
Well, let me explain what is happening here. We are telling Filament to render our Livewire component after the global search input, that is on the top right part of the navigation. Now you can take a look at your application and see the new button! Clicking on it won't do anything yet, but we'll fix this by adding the form fields and the action that will be executed when the form is submitted. Go back to your Livewire component class and add the following:
1public function openReportIssueModal(): Action 2{ 3 return Action::make('issues') 4 //... 5 ->form([ 6 Forms\Components\TextInput::make('subject') 7 ->label(__('Subject')) 8 ->placeholder('John Doe') 9 ->required(),10 11 Forms\Components\Textarea::make('description')12 ->label(__('Description'))13 ->placeholder('Describe the issue in a few words')14 ->rows(5)15 ->required(),16 ])17 ->action(function (array $data) {18 // Optionally, you can save the issue in the database...19 /*auth()->user()->issues()->create([20 'subject' => $data['subject'],21 'description' => $data['description'],22 ]);*/23 24 // ...or send yourself an email25 //Mail::to($data['email'])->send(...);26 27 // And finally, notify the user ... also optional!28 Notification::make('issueSubmitted')29 ->body('Thank you! The issue was submitted!')30 ->success()31 ->send();32 })33 ->link(); // This is optional, if you want your button to have a link aspect.34}
And this concludes our journey! Now you have a button in the top navigation that opens a modal with a form that, when submitted, will do what you would tell it to do 🙂! And don't limit to that behaviour, just use your imagination and do whatever Filament allows you to do! 🚀