Basic Usage
Creating a Form Class
Create a form class that extends Form and define your fields in the fields() method. You may generate one with Artisan:
php artisan make:form CreateUserFormOr create it manually:
namespace App\Forms;
use InertiaUI\Forms\Fields\Submit;
use InertiaUI\Forms\Fields\TextInput;
use InertiaUI\Forms\Form;
class CreateUserForm extends Form
{
protected ?string $actionRoute = 'users.store';
public function fields(): array
{
return [
TextInput::make('name')
->required()
->placeholder('Enter your name'),
TextInput::make('email')
->email()
->required()
->placeholder('you@example.com'),
Submit::make('Create User'),
];
}
}The $actionRoute property tells the form where to submit. It resolves to a named Laravel route. The HTTP method is automatically detected from the route definition.
Passing to Inertia
Use the static make() method to create a form instance and pass it as a prop to your page:
use App\Forms\CreateUserForm;
class UserController
{
public function create()
{
return Inertia::render('Users/Create', [
'form' => CreateUserForm::make(),
]);
}
}Behind the scenes, make() creates the form instance, and Inertia serializes it to JSON via the form's toArray() method. The result includes the action URL, HTTP method, field definitions, and initial data.
Rendering in Your Frontend
In your page component, import the Form component for your stack and pass the form prop:
<script setup>
import { Form } from '@inertiaui/form-vue'
defineProps(['form'])
</script>
<template>
<Form :form="form" />
</template>import { Form } from '@inertiaui/form-react'
export default function CreateUser({ form }) {
return <Form form={form} />
}That's it. The component reads the field definitions and renders the appropriate input component for each field, complete with labels, help text, error messages, and styling.
Handling Submission
Submitting the form sends an Inertia request to the action URL using the configured HTTP method. On the backend, handle the request like any other Inertia form submission:
class UserController
{
public function create()
{
return Inertia::render('Users/Create', [
'form' => CreateUserForm::make(),
]);
}
public function store(Request $request)
{
$validated = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'unique:users'],
]);
User::create($validated);
return redirect()->route('users.index');
}
}Or use the #[Validate] attribute to let the form handle validation automatically:
use InertiaUI\Forms\Validate;
class UserController
{
public function store(#[Validate] CreateUserForm $form)
{
$validated = $form->validated();
User::create($validated);
return redirect()->route('users.index');
}
}See the validation docs for more on the #[Validate] attribute.
Action Routes and Methods
The simplest way to set the form action is with the $actionRoute property:
class CreateUserForm extends Form
{
protected ?string $actionRoute = 'users.store';
}The HTTP method is inferred from the route definition.
When the named route needs parameters, pass them while making the form:
return Inertia::render('Users/Edit', [
'form' => EditUserForm::make()
->route('users.update', ['user' => $user]),
]);For a named route, Inertia Forms always uses the HTTP method declared by that route. Calling put(), patch(), or another method helper does not override a resolved named route. Use url() when the action is a raw URL and set its method explicitly:
EditUserForm::make()->url('/api/users/1')->patch();Events
The Form component accepts submission callbacks. In Vue they are emitted as events; in React they are passed as props:
<template>
<Form
:form="form"
@success="handleSuccess"
@error="handleError"
@finish="handleFinish"
/>
</template>
<script setup>
function handleSuccess() {
// Form submitted successfully
}
function handleError(errors) {
// Validation errors returned
}
function handleFinish() {
// Submission finished, after either success or error
}
</script>import { Form } from '@inertiaui/form-react'
export default function CreateUser({ form }) {
return (
<Form
form={form}
onSuccess={handleSuccess}
onError={handleError}
onFinish={handleFinish}
/>
)
}
function handleSuccess() {
// Form submitted successfully
}
function handleError(errors) {
// Validation errors returned
}
function handleFinish() {
// Submission finished, after either success or error
}success / onSuccess and finish / onFinish have no payload. error / onError receives the current validation error object. finish always runs after the request completes.