Record actions
Record actions work on one record. A resource returns them from
actions().
use Anvil\Resource\Action;use Anvil\Schema\Fields\DateInput;use Anvil\Schema\Form;
public function actions(): array{ return [ Action::make('finish') ->label('Finish')->icon('flag')->color('success') ->visible(fn ($project): bool => $project['status'] !== 'done') ->confirm('Finish the project?') ->inRow()->primary() ->handle(function ($project): string { $this->model()->update($this->recordKey($project), ['status' => 'done']);
return 'Project finished.'; }),
Action::make('leave') ->label('Record exit')->icon('box-arrow-right')->color('outline-danger') ->permission('people.lifecycle') ->form(static fn (Form $form): Form => $form->schema([ DateInput::make('exit_date')->required()->default(date('Y-m-d')), ])) ->handle(function ($person, array $data): string { service('iamLifecycle')->leave((int) $this->recordKey($person), (string) $data['exit_date']);
return 'The exit has been recorded.'; }), ];}Action::make() takes a camelCase name ([a-z][a-zA-Z0-9]*, at most 41
characters; otherwise an InvalidArgumentException). It identifies the
action at the endpoint, in the audit log and in the API
(markDone → /actions/mark-done). Names must be unique within the
resource.
Options
Section titled “Options”| Option | Effect | Default |
|---|---|---|
label('…') |
button text | the name with a capital letter |
icon('flag') |
Bootstrap icon | none |
color('success') |
button colour, see below | outline-secondary |
permission('people.lifecycle') |
required permission | <slug>.update |
visible(fn ($record) => …) |
only shown and executable when it returns true | always |
confirm('…') |
question before the action runs | none |
form(fn (Form $form, $record) => …) |
dialog with fields, see Actions with a form | none |
inRow() |
also in the rows and cards of the list | detail page only |
primary() |
shown as button in rows and cards before others | |
link('hr', '{value}', fn ($record) => …, target: …) |
opens a page of an external system | |
url(fn ($record) => …, target: …) |
opens a page of the application | |
handle(fn ($record, array $data) => …) |
the code that runs |
Colours: primary, secondary, success, danger, warning, info,
light, dark, outline-primary, outline-secondary, outline-success,
outline-danger, outline-warning. Others throw an
InvalidArgumentException. Use danger colours for actions that remove
or end something.
An action has either a handler or a link. An action with neither throws a
LogicException when it runs.
Running an action
Section titled “Running an action”->handle(function ($record, array $data): ?string { // ... return 'Done.'; // message shown to the user; null shows "Done"})$recordis the record as the model returns it (array or entity), loaded through the resource.$dataholds the validated, converted values of the form (an empty array without a form), e.g. the internal id for aBelongsTo.- The handler runs in a database transaction through the
component endpoint and is written to
the audit log as
component.actionwith the action name. Changes through Anvil models are audited as well. - An exception rolls everything back. Throw
EndpointException::forValidation(['field' => 'message'])for an error at a field of the dialog. - On the detail page the user is redirected to the detail page and sees the message; in the list the list is reloaded.
Keep handlers short: call a service that holds the business logic, so the same logic can be used by commands, jobs and the API.
Typical actions
Section titled “Typical actions”// Hand over a document for signing (see Documents)Action::make('issue')->label('Issue')->icon('box-arrow-right')->permission('receipts.manage') ->handle(function ($person): string { $document = service('documents')->create(new IssueReceipt(), $this, $person, [...]); service('handover')->start($this->panel(), $document, $this->path('view', $this->recordUuid($person)));
return 'The receipt is ready for signing.'; }),
// Notify somebody (see Notifications)Action::make('remind')->icon('bell') ->handle(function ($task): string { service('notifications')->send((int) $task['assignee_id'], Notification::make('Please finish ' . $task['title']));
return 'Reminder sent.'; }),