Quick Start
In this guide you build a "Create user" form: a PHP class, two routes, and one page.
1. Generate a form class
php artisan make:form CreateUserFormThis creates app/Forms/CreateUserForm.php. Replace its contents with:
<?php
namespace App\Forms;
use Erag\InertiaForms\Fields\Combobox;
use Erag\InertiaForms\Fields\Fieldset;
use Erag\InertiaForms\Fields\Submit;
use Erag\InertiaForms\Fields\TextInput;
use Erag\InertiaForms\Fields\Toggle;
use Erag\InertiaForms\Form;
class CreateUserForm extends Form
{
protected ?string $actionRoute = 'users.store';
public function fields(): array
{
return [
Fieldset::make('Account')->columns(2)->fields([
TextInput::make('name')->required()->maxLength(100),
TextInput::make('email')->email()->required()->rule('unique:users,email'),
TextInput::make('password')->password()->required()->minLength(8),
Combobox::make('role')->options([
'admin' => 'Admin',
'editor' => 'Editor',
])->required(),
]),
Toggle::make('send_welcome_email')->default(true),
Submit::make('Create user')->processingLabel('Creating…'),
];
}
}The form submits to the users.store route. The HTTP method (POST) is read from the route definition.
2. Add the routes
use App\Forms\CreateUserForm;
use App\Http\Controllers\UserController;
Route::get('/users/create', [UserController::class, 'create'])->name('users.create');
Route::post('/users', [UserController::class, 'store'])->name('users.store');3. Write the controller
<?php
namespace App\Http\Controllers;
use App\Forms\CreateUserForm;
use App\Models\User;
use Erag\InertiaForms\Attributes\Validate;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
class UserController extends Controller
{
public function create(): Response
{
return Inertia::render('Users/Create', [
'form' => CreateUserForm::make(),
]);
}
public function store(#[Validate] CreateUserForm $form): RedirectResponse
{
$user = User::create($form->validated());
if ($form->validated('send_welcome_email')) {
// Send the email...
}
return to_route('users.index');
}
}#[Validate] resolves the form from the container and validates the current request. If validation fails, Laravel redirects back and Inertia shows the errors under each field. See Validation for more options.
4. Render the page
<!-- resources/js/pages/Users/Create.vue -->
<script setup lang="ts">
import { Form, type FormSchema } from '@erag/inertia-forms-vue';
defineProps<{ form: FormSchema }>();
</script>
<template>
<div class="mx-auto max-w-2xl p-6">
<h1 class="mb-6 text-xl font-semibold">Create user</h1>
<Form :form="form" />
</div>
</template>// resources/js/pages/Users/Create.tsx
import { Form, type FormSchema } from '@erag/inertia-forms-react';
export default function Create({ form }: { form: FormSchema }) {
return (
<div className="mx-auto max-w-2xl p-6">
<h1 className="mb-6 text-xl font-semibold">Create user</h1>
<Form form={form} />
</div>
);
}<!-- resources/js/pages/Users/Create.svelte -->
<script lang="ts">
import { Form, type FormSchema } from '@erag/inertia-forms-svelte';
let { form }: { form: FormSchema } = $props();
</script>
<div class="mx-auto max-w-2xl p-6">
<h1 class="mb-6 text-xl font-semibold">Create user</h1>
<Form {form} />
</div>Open /users/create. You get a two-column "Account" section, a toggle, and a submit button that shows a spinner while the request runs.
What happened
- Labels came from field names:
send_welcome_emailbecame "Send welcome email". - Each field generated its own rules. For example,
emailgotrequired,string,email, plus yourunique:users,email. - The
rolecombobox only acceptsadminoreditor. - The toggle started as
truebecause of->default(true).
Try it
This is the form from step 1, rendered live. The route is left out because the docs have no backend, and only required fields are checked in the browser.
use Erag\InertiaForms\Fields\Combobox;
use Erag\InertiaForms\Fields\Fieldset;
use Erag\InertiaForms\Fields\Submit;
use Erag\InertiaForms\Fields\TextInput;
use Erag\InertiaForms\Fields\Toggle;
use Erag\InertiaForms\Form;
class CreateUserForm extends Form
{
public function fields(): array
{
return [
Fieldset::make('Account')->columns(2)->fields([
TextInput::make('name')->required()->maxLength(100),
TextInput::make('email')->email()->required()->rule('unique:users,email'),
TextInput::make('password')->password()->required()->minLength(8),
Combobox::make('role')->options([
'admin' => 'Admin',
'editor' => 'Editor',
])->required(),
]),
Toggle::make('send_welcome_email')->default(true),
Submit::make('Create user')->processingLabel('Creating…'),
];
}
}Going further: one form for create and edit
The same form, extended with three ideas from the next pages. Visibility shows the sections list only for editors. Model binding fills the form with an existing user. With a user bound, the email becomes read-only, and authorization removes the password and welcome email fields.
use Erag\InertiaForms\Fields\CheckboxGroup;
use Erag\InertiaForms\Fields\Combobox;
use Erag\InertiaForms\Fields\Fieldset;
use Erag\InertiaForms\Fields\Submit;
use Erag\InertiaForms\Fields\TextInput;
use Erag\InertiaForms\Fields\Toggle;
use Erag\InertiaForms\Form;
class UserForm extends Form
{
public function fields(): array
{
$editing = $this->getModel() !== null;
return [
Fieldset::make('Account')->columns(2)->fields([
TextInput::make('name')->required()->maxLength(100),
TextInput::make('email')->email()->required()->readonly($editing),
TextInput::make('password')->password()->required()->minLength(8)->authorizedUnless($editing),
Combobox::make('role')->options([
'admin' => 'Admin',
'editor' => 'Editor',
])->required(),
CheckboxGroup::make('sections')
->label('Sections this editor can publish to')
->inline()
->options(['news' => 'News', 'sport' => 'Sport', 'culture' => 'Culture'])
->required()
->visibleWhen('role', 'editor')
->columnSpan(2),
]),
Toggle::make('send_welcome_email')->default(true)->authorizedUnless($editing),
Submit::make($editing ? 'Save user' : 'Create user')->processingLabel('Saving…'),
];
}
}
// In the edit action: UserForm::make()->bind($user)
UserForm::make()->bind([
'name' => 'Jane Cooper',
'email' => 'jane@example.com',
'role' => 'editor',
'sections' => ['news', 'culture'],
]);Next steps
- Learn every option of the Form class.
- Show fields only when needed with Conditional Visibility.
- Reuse the form for editing with Model Binding.