F
Filament4mo ago
w5m

Custom "Save" button to create or save a form

I'm trying to add a custom "Save" button (i.e. action) to a form.
...
use Filament\Forms\Components\Actions\Action;
...

public static function form(Form $form): Form
{
return $form
->schema([
Section::make('Parameters')
->schema(...)
->footerActions([
Action::make('save')
->label('Save')
->action('save'),
]),
...
...
use Filament\Forms\Components\Actions\Action;
...

public static function form(Form $form): Form
{
return $form
->schema([
Section::make('Parameters')
->schema(...)
->footerActions([
Action::make('save')
->label('Save')
->action('save'),
]),
...
If I pass the string 'save' to the ->action() method, it successfully saves changes to any form fields if I'm Editing a record and click the "Save" button. However, if I'm Creating a record and click the "Save" button, I see an error: Unable to call component method. Public method [save] not found on component. If I pass the string 'create' to the ->action() method, it successfully saves the values in the form fields if I'm Creating a record and click the "Save" button. However, if I'm Editing a record and click the "Save" button, I see an error: Unable to call component method. Public method [create] not found on component . I tried passing a closure to the ->action() method to return the appropriate string depending on the type of form, but this causes nothing to happen on clicking the "Save" button... ->action(fn ($operation) => ($operation === 'edit') ? 'save' : 'create') I'm guessing that ultimately my closure needs to return an object, rather than a string, but I'm not clear what that object should be. Any pointers would be gratefully received.
Solution:
You could create a trait with a custom method and use this in Create/Edit page.. ```php public function createOrSave(): void {...
Jump to solution
2 Replies
Solution
LeandroFerreira
LeandroFerreira4mo ago
You could create a trait with a custom method and use this in Create/Edit page..
public function createOrSave(): void
{
match (class_basename($this)) {
default => null,
'CreatePage' => $this->create(),
'EditPage' => $this->save()
};
}
public function createOrSave(): void
{
match (class_basename($this)) {
default => null,
'CreatePage' => $this->create(),
'EditPage' => $this->save()
};
}
Action::make('save')->action('createOrSave')
Action::make('save')->action('createOrSave')
w5m
w5mOP4mo ago
A big thank you for your suggestion @Leandro Ferreira - that's a nice way of doing it and I now have a better understanding of which methods the 'save' and 'create' strings were referring to. I slightly adapted the custom method you suggested to fit with my implementation (as I have an additional class named BaseCreateRecord which descends from CreateRecord and introduces some common functionality to child classes)...
trait CanCreateOrSave {
/**
* Calls the appropriate method to either create a new record,
* or save changes to an existing record.
* This method name can be passed to an the ->action() method
* of an Action component.
*/
public function createOrSave(): void
{
if (is_subclass_of($this, \Filament\Resources\Pages\CreateRecord::class)) {
$this->create();
} else if (is_subclass_of($this, \Filament\Resources\Pages\EditRecord::class)) {
$this->save();
}
}
}
trait CanCreateOrSave {
/**
* Calls the appropriate method to either create a new record,
* or save changes to an existing record.
* This method name can be passed to an the ->action() method
* of an Action component.
*/
public function createOrSave(): void
{
if (is_subclass_of($this, \Filament\Resources\Pages\CreateRecord::class)) {
$this->create();
} else if (is_subclass_of($this, \Filament\Resources\Pages\EditRecord::class)) {
$this->save();
}
}
}
Want results from more Discord servers?
Add your server