Show modal instead of toast after CreateRecord in Filament v4

Hi! 👋 I’m building a CreateRecord in Filament where I generate a Passport Client. In the handleRecordCreation() method I get the client_id and the plainSecret (only available right after creating the client). Currently, I’m displaying these values in a toast notification using getCreatedNotification(), but instead I’d like to show them in a modal (so the user can easily copy them). My question is: Is it possible to replace the toast notification with a modal in the CreateRecord flow? And if so, what’s the recommended approach in Filament v4? (e.g. using afterCreate + Filament modal, or is there something built-in like with notifications?). Thanks in advance! 🙏
2 Replies
Juliancho Dev
Juliancho DevOP•3w ago
this is my method getCreatedNotification
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Cliente registrado')
->body("Se ha creado un nuevo cliente. Recuerda anotar el Client ID y el Client SECRET. Esta no se repetirá <br>ID: " . $this->id . "<br> Secret: " . $this->secretClient)
->send();
}
protected function getCreatedNotification(): ?Notification
{
return Notification::make()
->success()
->title('Cliente registrado')
->body("Se ha creado un nuevo cliente. Recuerda anotar el Client ID y el Client SECRET. Esta no se repetirá <br>ID: " . $this->id . "<br> Secret: " . $this->secretClient)
->send();
}
Povilas Korop
Povilas Korop•3w ago
Hey, I was curious about this problem so made a few attempts with chatgpt and one of them did work, use this code as an idea. But also, I'm not sure I like this workflow, as then the user stays on the page of Create, so UX is pretty weird.
class CreateTask extends CreateRecord
{
protected static string $resource = TaskResource::class;
public ?string $name = null;

protected function handleRecordCreation(array $data): \Illuminate\Database\Eloquent\Model
{
$this->name = $data['name'];

// return the Eloquent model you created:
return static::getModel()::create($data);
}

protected function afterCreate(): void
{
// Show the secrets in a modal as soon as the record is created:
$this->mountAction('showSecrets');

$this->halt();
}

// Turn off the default toast:
protected function getCreatedNotification(): ?Notification
{
return null;
}

protected function getCreateFormAction(): Action
{
return parent::getCreateFormAction()
->successNotification(null) // disable toast on the button itself
->successRedirectUrl(null); // no redirect after save
}
}
class CreateTask extends CreateRecord
{
protected static string $resource = TaskResource::class;
public ?string $name = null;

protected function handleRecordCreation(array $data): \Illuminate\Database\Eloquent\Model
{
$this->name = $data['name'];

// return the Eloquent model you created:
return static::getModel()::create($data);
}

protected function afterCreate(): void
{
// Show the secrets in a modal as soon as the record is created:
$this->mountAction('showSecrets');

$this->halt();
}

// Turn off the default toast:
protected function getCreatedNotification(): ?Notification
{
return null;
}

protected function getCreateFormAction(): Action
{
return parent::getCreateFormAction()
->successNotification(null) // disable toast on the button itself
->successRedirectUrl(null); // no redirect after save
}
}
And then inside also:
protected function getActions(): array
{
return [
Action::make('showSecrets')
->modalHeading('Copy your task name')
->modalDescription('These values are shown only once. Store them securely.')
->modalSubmitAction(false) // no primary submit button
->modalCancelAction(fn (Action $a) => $a->label('Done'))
->closeModalByClickingAway(false)
->schema([
TextInput::make('name')
->label('Name')
->default(fn () => $this->name)
->readOnly()
->dehydrated(false)
->copyable(copyMessage: 'Copied!', copyMessageDuration: 1500),
])
];
}
protected function getActions(): array
{
return [
Action::make('showSecrets')
->modalHeading('Copy your task name')
->modalDescription('These values are shown only once. Store them securely.')
->modalSubmitAction(false) // no primary submit button
->modalCancelAction(fn (Action $a) => $a->label('Done'))
->closeModalByClickingAway(false)
->schema([
TextInput::make('name')
->label('Name')
->default(fn () => $this->name)
->readOnly()
->dehydrated(false)
->copyable(copyMessage: 'Copied!', copyMessageDuration: 1500),
])
];
}
So, it "kinda" works but I wouldn't probably recommend it. Maybe choose to redirect to a separate PAGE instead with copyable things and then navigate from there?

Did you find this page helpful?