Submit
Erag\InertiaForms\Fields\Submit renders a submit button. While the form is submitting, the button is disabled and shows a spinner. You can style it with variants, sizes and an icon, and put several buttons in one form, each sending its own intent.
When to use: every form that needs a custom button text, a "processing" text, a specific position or style for the button, or more than one action.
Unlike other fields, the argument to make() is the button text, not a data key.
Try several buttons on the Landing page form in the Live Demo.
Examples
Each example is a live form built from the PHP below it. Fill it in and press submit to see the data your controller would receive.
Variants
Every style side by side. Buttons that follow each other share one row.
use Erag\InertiaForms\Fields\Submit;
[
Submit::make('Primary'),
Submit::make('Secondary')->secondary(),
Submit::make('Outline')->outline(),
Submit::make('Ghost')->ghost(),
Submit::make('Link')->link(),
Submit::make('Danger')->danger(),
];Sizes
small(), the default md, and large().
use Erag\InertiaForms\Fields\Submit;
[
Submit::make('Small')->small(),
Submit::make('Medium'),
Submit::make('Large')->large(),
];Icons and full width
A sign-in form with a full-width button and an icon after the text. During a real request, a spinner replaces the icon and processingLabel() replaces the text.
use Erag\InertiaForms\Fields\Submit;
use Erag\InertiaForms\Fields\TextInput;
[
TextInput::make('email')->email()->required(),
TextInput::make('password')->password()->required(),
Submit::make('Sign in')
->icon('arrowRight', 'right')
->processingLabel('Signing in…')
->fullWidth(),
];Advanced: two actions
"Save draft" and "Publish" submit the same fields, and the clicked button adds its value under intent (draft or publish), so your controller can tell them apart. Try both buttons: the submitted data shows the intent. onBeforeSubmit receives it too.
use Erag\InertiaForms\Fields\Submit;
use Erag\InertiaForms\Fields\Textarea;
use Erag\InertiaForms\Fields\TextInput;
[
TextInput::make('title')->required(),
Textarea::make('body')->rows(3),
Submit::make('Save draft')
->secondary()
->icon('save')
->intent('draft'),
Submit::make('Publish')
->icon('send', 'right')
->intent('publish')
->processingLabel('Publishing…'),
];Advanced: save only after a change
An edit form filled from a model. "Save changes" stays disabled until a value changes, and turns off again when the value is changed back.
use Erag\InertiaForms\Fields\Submit;
use Erag\InertiaForms\Fields\TextInput;
use Erag\InertiaForms\Form;
class EditProfileForm extends Form
{
public function fields(): array
{
return [
TextInput::make('name')->required(),
TextInput::make('email')->email()->required(),
Submit::make('Save changes')
->icon('check')
->disableUntilDirty(),
];
}
}
EditProfileForm::make()->bind([
'name' => 'Ada Lovelace',
'email' => 'ada@example.com',
]);Methods
processingLabel(?string $label)
Text shown on the button while the request is running. Without it, the normal text stays and only the spinner appears.
Submit::make('Save')->processingLabel('Saving…');variant(string $variant)
The button style. One of:
| Variant | Shortcut | Look |
|---|---|---|
primary (default) | primary() | Filled with the accent color |
secondary | secondary() | Neutral, for the less important action |
danger | danger() | Red, for destructive actions |
outline | outline() | Border only |
ghost | ghost() | No border or background until hovered |
link | link() | Looks like a text link |
Any other value throws an InvalidArgumentException.
Submit::make('Delete project')->danger();size(string $size)
sm, md (default) or lg. The shortcuts small() and large() do the same. Any other value throws an InvalidArgumentException.
fullWidth(bool $fullWidth = true)
Stretch the button across its row. Handy on narrow forms and in sign-in screens.
icon(?string $icon, string $position = 'left')
Show a package icon, like user, check, send, arrowRight or trash, before the text. Pass 'right' as the second argument to put it after the text. See Icons for every name.
Submit::make('Continue')->icon('arrowRight', 'right');intent(string $value, string $key = 'intent')
Send key => value with the form when this button is clicked. Use it to offer several actions in one form:
Submit::make('Save draft')->secondary()->intent('draft'),
Submit::make('Publish')->icon('send', 'right')->intent('publish')->processingLabel('Publishing…'),The form accepts only the values of its own buttons: the rules get 'intent' => ['nullable', 'string', Rule::in(['draft', 'publish'])], so a request with intent=delete fails validation. The value is part of validated():
public function store(#[Validate] PageForm $form)
{
$page = Page::create(Arr::except($form->validated(), 'intent'));
if ($form->validated('intent') === 'publish') {
$page->publish();
}
return to_route('pages.index');
}Buttons can use different keys (intent('archive', 'action')); each key gets its own rule. When the form is sent without clicking an intent button, the key is empty, so give it a default in your controller.
disableUntilDirty(bool $disable = true)
Keep the button disabled until the user changes a value. Useful for "Save changes" on an edit form, so nobody sends a request that changes nothing.
Submit::make('Save changes')->disableUntilDirty();The form is dirty when any value differs from its starting value. After a successful submit the saved values become the new starting point, so the button turns off again. The frontend can read the same state; see Unsaved changes.
Common methods that apply
| Method | Effect |
|---|---|
label(?string $label) | Overrides the button text set in make(). |
disabled(bool $disabled = true) | Disables the button. |
class(?string $class) | Extra classes on the button's wrapper row, for example 'justify-end'. |
visibleWhen() / hiddenWhen() | Show the button only in some states. |
authorize() / authorizedWhen() / authorizedUnless() | Remove the button for some users. |
Other common methods (help(), placeholder(), required(), rules(), columnSpan(), ...) have no effect on the button.
Placement
The button renders where you put it in fields(). Buttons that follow each other share one row, so a "Save draft" and a "Publish" button sit side by side. Most forms put them last:
public function fields(): array
{
return [
Fieldset::make('Profile')->columns(2)->fields([...]),
Submit::make('Save profile')->class('justify-end'),
];
}If a form has no Submit field, <Form> adds a default "Submit" button at the end, after any content you pass as children. Add a Submit field to control its text and position. Forms with a Composer use its Send button instead, and in a wizard the buttons appear on the last step.
Validation rules
None for the button itself. It carries no value, so it is not part of the form data. Buttons with intent() add one rule per key, as shown above.
Value
No value. data() never contains the button. With intent(), validated() contains the intent key and the value of the clicked button, like ['intent' => 'publish'].
Standalone use
SubmitButton is exported for custom layouts. It does not use the field props contract; it takes these props instead:
| Prop | Type | Description |
|---|---|---|
label | string | Button text. |
processingLabel | string | null | Optional text while processing. |
processing | boolean | Shows the spinner and disables the button. |
disabled | boolean | Optional. Disables the button. |
Inside <Form>, the style options (variant, size, fullWidth, icon, iconPosition) and the intent are read from the serialized Submit field. See Serialized Schema.
<SubmitButton label="Save" processing-label="Saving…" :processing="form.processing" class="justify-end" /><SubmitButton label="Save" processingLabel="Saving…" processing={form.processing} className="justify-end" /><SubmitButton label="Save" processingLabel="Saving…" processing={form.processing} class="justify-end" />The button has type="submit", so place it inside your own <form>. Extra classes go on its wrapper row (class in Vue and Svelte, className in React).