Documentation Index
Fetch the complete documentation index at: https://mintlify.com/filamentphp/filament/llms.txt
Use this file to discover all available pages before exploring further.
The Create Page
The Create page displays a form for creating new records. When you generate a resource, Filament creates a CreateCustomer.php page class:
packages/panels/src/Resources/Pages/CreateRecord.php
class CreateRecord extends Page
{
public ?array $data = [];
protected static bool $canCreateAnother = true;
public function create(bool $another = false): void
{
// Creation logic
}
}
The create form is defined in your resource’s form() method. This is typically referenced from a separate schema file:
use App\Filament\Resources\Customers\Schemas\CustomerForm;
use Filament\Schemas\Schema;
public static function form(Schema $schema): Schema
{
return CustomerForm::configure($schema);
}
In the form schema file:
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Schema;
public static function configure(Schema $schema): Schema
{
return $schema
->components([
TextInput::make('name')
->required()
->maxLength(255),
TextInput::make('email')
->email()
->required(),
]);
}
Validation
Validation is handled automatically through field rules:
TextInput::make('email')
->email()
->required()
->unique(Customer::class, 'email'),
TextInput::make('phone')
->tel()
->rules(['regex:/^[0-9]{10}$/']),
Validation runs when the form is submitted, before beforeCreate() hook.
Lifecycle Hooks
Hooks allow you to execute code at specific points in the creation process:
packages/panels/src/Resources/Pages/CreateRecord.php
protected function beforeFill(): void
{
// Runs before the form fields are populated with default values
}
protected function afterFill(): void
{
// Runs after the form fields are populated with default values
}
protected function beforeValidate(): void
{
// Runs before the form fields are validated
}
protected function afterValidate(): void
{
// Runs after the form fields are validated
}
protected function beforeCreate(): void
{
// Runs before the form fields are saved to the database
}
protected function afterCreate(): void
{
// Runs after the form fields are saved to the database
}
Adding User ID
Sending Email
Logging Activity
protected function mutateFormDataBeforeCreate(array $data): array
{
$data['user_id'] = auth()->id();
return $data;
}
protected function afterCreate(): void
{
Mail::to($this->record->email)
->send(new WelcomeEmail($this->record));
}
protected function afterCreate(): void
{
activity()
->performedOn($this->record)
->log('Customer created');
}
Mutating Data
Modify form data before saving:
packages/panels/src/Resources/Pages/CreateRecord.php
protected function mutateFormDataBeforeCreate(array $data): array
{
$data['user_id'] = auth()->id();
$data['status'] = 'pending';
return $data;
}
Customizing Creation Process
Override how records are created:
packages/panels/src/Resources/Pages/CreateRecord.php
protected function handleRecordCreation(array $data): Model
{
$record = new ($this->getModel())($data);
if ($parentRecord = $this->getParentRecord()) {
return $this->associateRecordWithParent($record, $parentRecord);
}
$record->save();
return $record;
}
For custom creation logic:
use Illuminate\Database\Eloquent\Model;
protected function handleRecordCreation(array $data): Model
{
// Custom creation logic
$customer = Customer::create([
'name' => $data['name'],
'email' => $data['email'],
]);
// Create related records
$customer->settings()->create([
'theme' => 'dark',
]);
return $customer;
}
Redirects After Creation
By default, users are redirected to the Edit page (or View page if it exists).
Redirect to List Page
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('index');
}
Redirect to View Page
protected function getRedirectUrl(): string
{
return $this->getResource()::getUrl('view', ['record' => $this->getRecord()]);
}
Redirect to Previous Page
protected function getRedirectUrl(): string
{
return $this->previousUrl ?? $this->getResource()::getUrl('index');
}
Global Redirect Configuration
Set a default redirect for all resources:
use Filament\Panel;
public function panel(Panel $panel): Panel
{
return $panel
->resourceCreatePageRedirect('index') // or 'view' or 'edit'
// ...
}
Success Notifications
Customize the success notification:
packages/panels/src/Resources/Pages/CreateRecord.php
protected function getCreatedNotificationTitle(): ?string
{
return 'Customer registered successfully';
}
For complete customization:
use Filament\Notifications\Notification;
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Customer registered')
->body('The customer has been created successfully.');
}
To disable notifications:
protected function getCreatedNotification(): ?Notification
{
return null;
}
Create Another
The “Create & create another” button allows users to create multiple records quickly.
Disabling Create Another
protected static bool $canCreateAnother = false;
Or dynamically:
public function canCreateAnother(): bool
{
return auth()->user()->can('create_multiple_customers');
}
Keep some fields filled when creating another record:
packages/panels/src/Resources/Pages/CreateRecord.php
use Illuminate\Support\Arr;
protected function preserveFormDataWhenCreatingAnother(array $data): array
{
return Arr::only($data, ['organization_id', 'country']);
}
To preserve all data:
protected function preserveFormDataWhenCreatingAnother(array $data): array
{
return $data;
}
Halting Creation
Stop the creation process at any point:
use Filament\Actions\Action;
use Filament\Notifications\Notification;
protected function beforeCreate(): void
{
if (! auth()->user()->team->subscribed()) {
Notification::make()
->warning()
->title('You don\'t have an active subscription!')
->body('Choose a plan to continue.')
->persistent()
->actions([
Action::make('subscribe')
->button()
->url(route('subscribe'), shouldOpenInNewTab: true),
])
->send();
$this->halt();
}
}
Wizards
Transform the create page into a multi-step wizard:
Add the trait
packages/panels/src/Resources/Pages/CreateRecord.php
use App\Filament\Resources\Categories\CategoryResource;
use Filament\Resources\Pages\CreateRecord;
class CreateCategory extends CreateRecord
{
use CreateRecord\Concerns\HasWizard;
protected static string $resource = CategoryResource::class;
}
Define steps
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Wizard\Step;
protected function getSteps(): array
{
return [
Step::make('Name')
->description('Give the category a clear and unique name')
->schema([
TextInput::make('name')->required(),
TextInput::make('slug')->required(),
]),
Step::make('Description')
->schema([
// ...
]),
];
}
Allow skipping (optional)
public function hasSkippableSteps(): bool
{
return true;
}
Custom Actions
Add custom buttons to the form:
use Filament\Actions;
protected function getHeaderActions(): array
{
return [
Actions\ImportAction::make()
->importer(CustomerImporter::class),
];
}
use Filament\Actions\Action;
protected function getFormActions(): array
{
return [
...parent::getFormActions(),
Action::make('createAndEmail')
->action('createAndEmail'),
];
}
public function createAndEmail(): void
{
// Custom logic
}
protected function getHeaderActions(): array
{
return [
$this->getCreateFormAction()
->formId('form'),
];
}
protected function getFormActions(): array
{
return [];
}
Authorization
Users can access the Create page if the create() method of the model policy returns true:
public function create(User $user): bool
{
return $user->can('create customers');
}