Skip to content

Schemas

A schema is the list of components you pass to $form->schema([...]). A component is either a field or a layout from Anvil\Schema\Layout: Grid, Section, Tabs with Tab, Wizard with Step. Layouts only arrange fields; they never change what is validated or saved – except that a hidden layout hides its fields.

The same schema is used for the create form, the edit form and – read-only – the detail page of a resource. Dialogs of actions and bulk actions take a schema as well.

use Anvil\Schema\Fields\DateInput;
use Anvil\Schema\Fields\Select;
use Anvil\Schema\Fields\Textarea;
use Anvil\Schema\Fields\TextInput;
use Anvil\Schema\Fields\Toggle;
use Anvil\Schema\Form;
use Anvil\Schema\Layout\Section;
use Anvil\Schema\Layout\Tab;
use Anvil\Schema\Layout\Tabs;
public function form(Form $form): Form
{
return $form->schema([
Tabs::make()->tabs([
Tab::make('Contact')->icon('person')->columns(2)->schema([
TextInput::make('name')->required()->maxLength(120),
TextInput::make('company')->maxLength(120),
TextInput::make('email')->email()->required(),
TextInput::make('phone')->tel()->maxLength(40),
]),
Tab::make('Relationship')->icon('people')->columns(2)->schema([
Select::make('status')->options(self::STATUSES)->required()->default('lead'),
DateInput::make('first_contact_on')->label('First contact'),
Toggle::make('newsletter')->label('Receives newsletter'),
]),
]),
Section::make('Notes')
->description('Internal, not visible to the contact.')
->collapsed()
->schema([Textarea::make('notes')->rows(4)]),
]);
}
Layout Use it for Details
Grid::make(2, [...]) fields side by side, without frame Grid
Section::make('Heading') a titled group, optionally collapsible Section
Tabs::make()->tabs([Tab::make('…')]) long forms in parts Tabs
Wizard::make()->steps([Step::make('…')]) creation step by step Wizard
own layouts anything else Own layouts

How wide fields and layouts are: Columns. Which parts are shown in create, edit and view: Visibility.

Method Effect
$form->schema([...]) the components, top level
$form->columns(2) columns of the top level, 1 to 4 (default 1)

Layouts can be nested, e.g. sections inside a tab or a grid inside a section. Keep it shallow: one level of tabs or steps with sections inside is usually enough.

Tabs::make()->tabs([
Tab::make('Person')->schema([
Section::make('Name')->columns(2)->schema([...]),
Section::make('Address')->collapsed()->schema([
Grid::make(3, [...]),
]),
]),
]),

A field name must be unique in the whole schema, across all layouts.

When the server rejects the input (HTTP 422), the form shows the messages next to the fields, then opens the collapsed section, the tab or the wizard step of the first invalid field and focuses it. Users never have to search for an error that is hidden behind a tab.