Actions

Overview

Actions are buttons that run PHP, with confirmation, modal fields, authorization and notifications.

An action is a button that runs PHP on the server. Put them in a form with the Actions layout.

use Xelqun\Actions\Action;
use Xelqun\Forms\Components\TextInput;
use Xelqun\Forms\Layouts\Actions;
use Xelqun\Forms\State\Get;
use Xelqun\Forms\State\Set;

Actions::make([
    Action::make('discount')
        ->authorize(true)
        ->icon('tag')
        ->fillForm(['percent' => 10])
        ->schema([
            TextInput::make('percent')->integer()->minValue(1)->maxValue(90)->required(),
        ])
        ->action(function (array $data, Get $get, Set $set): void {
            $set('price', round($get('price') * (100 - $data['percent']) / 100, 2));
        }),
]);

Each click rebuilds the form on the server and checks the action again.

Authorization

An action does nothing without authorize(), and the form's authorize() doesn't count.

authorize() takes a boolean, a closure, or a policy ability checked against the record.

Action::make('publish')->authorize('update');

Action::make('refund')->authorize(fn (): bool => auth()->user()->isManager());

What an action can do

action() runs inside a transaction. It gets $data, $get, $set and $record.

Action::make('archive')
    ->authorize('update')
    ->requiresConfirmation()
    ->action(fn (Order $record) => $record->update(['archived_at' => now()]));

url() goes to a URL and runs nothing.

Action::make('invoice')->authorize(true)->url(fn (): string => route('invoice'), openInNewTab: true);

Throw a ValidationException to send an error back to the form.

How it looks

Method What it does
label(), icon(), color(), tooltip() Change what's shown.
button() Shows a button, which is the default.
link() Shows a link.
iconButton() Shows only the icon. The label stays for screen readers.
disabled(), hidden(), visible() Follow a boolean or a closure.

After it runs

Action::make('save')
    ->authorize(true)
    ->successNotificationTitle('Saved')
    ->successRedirectUrl(fn (): string => route('orders.index'))
    ->action(fn () => null);

record() gives the action another record to work on, and model() names the model its modal fields and policy use.

Actions in other places

  • prefixAction() and suffixAction() sit beside a field.
  • extraItemActions() sit in a repeater row's header.
  • Standalone actions sit on a page, with no form.
  • Table actions sit on a table's rows.