Filament is great for creating full CRUDs in Resources. But what if you want to create just a single Edit form for one specific record, without the full Resource? Let's use a Custom Page for it.
In this example, we will use a company that belongs to a user.
The idea comes from the question on the official Filament Discord:
Here's the result of what we're gonna be building.
Prepare Custom Page
The main thing you need to understand that it's sometimes easier to create a Custom Page with just the actions you want than to create a full Filament Resource and then try to "strip it down".
Also, Filament comes with separated packages, so you can use Filament Forms/Tables even outside of Filament, in Livewire components.
So first, create a custom page and prepare it to use Filament Forms.
php artisan make:filament-page EditCompany --type=custom
Notice: when creating a custom page, don't specify any associated Resource.
Now, we need to implement an interface and add a trait to use Filament forms.
app/Filament/Pages/EditCompany.php:
use Filament\Forms\Contracts\HasForms;use Filament\Forms\Concerns\InteractsWithForms; class EditCompany extends Page implements HasForms{ use InteractsWithForms;}
Custom page now can use Filament Forms, so let's add a form.
app/Filament/Pages/EditCompany.php:
use Filament\Forms\Form;use Filament\Forms\Components\TextInput;use Filament\Forms\Concerns\InteractsWithForms; class EditCompany extends Page implements HasForms{ use InteractsWithForms; public ?array $data = []; protected static ?string $navigationIcon = 'heroicon-o-document-text'; protected static string $view = 'filament.pages.edit-company'; public function mount(): void { $this->form->fill(); } public function form(Form $form): Form { return $form ->schema([ TextInput::make('name') ->required(), ]) ->statePath('data'); } }
And we need to render the form in the Blade file.
resources/views/filament/pages/edit-company.blade.php:
<x-filament-panels::page> <x-filament-panels::form> {{ $this->form }} </x-filament-panels::form></x-filament-panels::page>
After visiting the edit company page, we now see an empty form.
Filling and Submitting Form
We must fill form inputs with the company information first. Because here we have a hasOne
relation to the company, we get all the company data by just doing auth()->user()->company
.
app/Models/User.php:
use Illuminate\Database\Eloquent\Relations\HasOne; class User extends Authenticatable implements FilamentUser{ // ... public function company(): HasOne { return $this->hasOne(Company::class); }}
app/Filament/Pages/EditCompany.php:
class EditCompany extends Page implements HasForms{ // ... public function mount(): void { $this->form->fill(); $this->form->fill(auth()->user()->company->attributesToArray()); } // ...}
Next, we need a submit button.
app/Filament/Pages/EditCompany.php:
use Filament\Actions\Action; class EditCompany extends Page implements HasForms{ // ... protected function getFormActions(): array { return [ Action::make('save') ->label(__('filament-panels::resources/pages/edit-record.form.actions.save.label')) ->submit('save'), ]; }}
resources/views/filament/pages/edit-company.blade.php:
<x-filament-panels::page> <x-filament-panels::form> {{ $this->form }} <x-filament-panels::form.actions :actions="$this->getFormActions()" /> </x-filament-panels::form></x-filament-panels::page>
After revisiting the edit company page, we can see the form is filled with data, and we have a submit button.
All that's left is to update the data. We need a method for updating the company and to add wire:submit
directive to the form.
resources/views/filament/pages/edit-company.blade.php:
<x-filament-panels::page> <x-filament-panels::form> <x-filament-panels::form wire:submit="save"> {{ $this->form }} <x-filament-panels::form.actions :actions="$this->getFormActions()" /> </x-filament-panels::form></x-filament-panels::page>
app/Filament/Pages/EditCompany.php:
use Filament\Support\Exceptions\Halt; class EditCompany extends Page implements HasForms{ // ... public function save(): void { try { $data = $this->form->getState(); auth()->user()->company->update($data); } catch (Halt $exception) { return; } } // ...}
Lastly, let's send a success notification message after updating company information.
use Filament\Notifications\Notification; class EditCompany extends Page implements HasForms{ // ... public function save(): void { try { $data = $this->form->getState(); auth()->user()->company->update($data); } catch (Halt $exception) { return; } Notification::make() ->success() ->title(__('filament-panels::resources/pages/edit-record.notifications.saved.title')) ->send(); } // ...}
Excellent!
Can show an example of how to add a custom
Clear
button with notification? i.e. After clicking onClear
button, it can clear/reset some fields of this record and show a notification that this record wasCleared
Just make an action button where action would be to set fields to initial value and send the notification
I could not get things to work, that's why I asked for an example.
It was an excellent elaboration that might help build any predefined settings page like Site title, Notification Email, Enable/Disable any feature, Some footer link, or many more things.
One thing I would like to address, HasForms interface is an unnecessary implementation. It is already announced in Filament\Pages\Page. So we might remove it as I Think.
Thanks
Kinda. But for settings you should use official plugin for spatie laravel settings package