Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Forms Laravel Package

filament/forms

Filament Forms is a Laravel package for building powerful, reactive admin forms with a fluent, component-based API. Create fields, layouts, validation, conditional logic, and dynamic interactions quickly, with tight Livewire integration and great DX for panels and apps.

View on GitHub
Deep Wiki
Context7

title: Overview

import Aside from "@components/Aside.astro" import AutoScreenshot from "@components/AutoScreenshot.astro" import UtilityInjection from "@components/UtilityInjection.astro"

Introduction

Filament's forms package allows you to easily build dynamic forms in your app. It's used within other Filament packages to render forms within panel resources, action modals, table filters, and more. Learning how to build forms is essential to learning how to use these Filament packages.

This guide will walk you through the basics of building forms with Filament's form package. If you're planning to add a new form to your own Livewire component, you should do that first and then come back. If you're adding a form to a panel resource, or another Filament package, you're ready to go!

Form fields

Form field classes can be found in the Filament\Form\Components namespace. They reside within the schema array of components. Filament ships with many types of field, suitable for editing different types of data:

You may also create your own custom fields to edit data however you wish.

Fields may be created using the static make() method, passing its unique name. Usually, the name of a field corresponds to the name of an attribute on an Eloquent model:

use Filament\Forms\Components\TextInput;

TextInput::make('name')

You may use "dot notation" to bind fields to keys in arrays:

use Filament\Forms\Components\TextInput;

TextInput::make('socials.github_url')

Validating fields

In Laravel, validation rules are usually defined in arrays like ['required', 'max:255'] or a combined string like required|max:255. This is fine if you're exclusively working in the backend with simple form requests. But Filament is also able to give your users frontend validation, so they can fix their mistakes before any backend requests are made.

In Filament, you can add validation rules to your fields by using methods like required() and maxLength(). This is also advantageous over Laravel's validation syntax, since your IDE can autocomplete these methods:

use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\RichEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;

TextInput::make('name')
    ->required()
    ->maxLength(255)

In this example, the fields is required(), and has a maxLength(). We have methods for most of Laravel's validation rules, and you can even add your own custom rules.

Setting a field's label

By default, the label of the field will be automatically determined based on its name. To override the field's label, you may use the label() method:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->label('Full name')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the label() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Customizing the label in this way is useful if you wish to use a translation string for localization:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->label(__('fields.name'))

Hiding a field's label

It may be tempting to set the label to an empty string to hide it, but this is not recommended. Setting the label to an empty string will not communicate the purpose of the field to screen readers, even if the purpose is clear visually. Instead, you should use the hiddenLabel() method, so it is hidden visually but still accessible to screen readers:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->hiddenLabel()

Optionally, you may pass a boolean value to control if the label should be hidden or not:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->hiddenLabel(FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the hiddenLabel() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Setting the default value of a field

Fields may have a default value. The default is only used when a schema is loaded with no data. In a standard panel resource, defaults are used on the Create page, not the Edit page. To define a default value, use the default() method:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->default('John')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the default() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Disabling a field

You may disable a field to prevent it from being edited by the user:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->disabled()

Optionally, you may pass a boolean value to control if the field should be disabled or not:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->disabled(! FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the disabled() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Disabling a field will prevent it from being saved. If you'd like it to be saved, but still not editable, use the saved() method:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->disabled()
    ->saved()

Optionally, you may pass a boolean value to control if the field should be saved or not:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->disabled()
    ->saved(FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the saved() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Disabling a field based on the current operation

The "operation" of a schema is the current action being performed on it. Usually, this is either create, edit or view, if you are using the panel resource.

You can disable a field based on the current operation by passing an operation to the disabledOn() method:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->disabledOn('edit')

// is the same as

Toggle::make('is_admin')
    ->disabled(fn (string $operation): bool => $operation === 'edit')

You can also pass an array of operations to the disabledOn() method, and the field will be disabled if the current operation is any of the operations in the array:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->disabledOn(['edit', 'view'])
    
// is the same as

Toggle::make('is_admin')
    ->disabled(fn (string $operation): bool => in_array($operation, ['edit', 'view']))

Hiding a field

You may hide a field:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->hidden()

Optionally, you may pass a boolean value to control if the field should be hidden or not:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->hidden(! FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the hidden() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Alternatively, you may use the visible() method to control if the field should be hidden or not. In some situations, this may help to make your code more readable:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->visible(FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the visible() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Hiding a field using JavaScript

If you need to hide a field based on a user interaction, you can use the hidden() or visible() methods, passing a function that uses utilities injected to determine whether the field should be hidden or not:

use Filament\Forms\Components\Select;
use Filament\Forms\Components\Toggle;

Select::make('role')
    ->options([
        'user' => 'User',
        'staff' => 'Staff',
    ])
    ->live()

Toggle::make('is_admin')
    ->hidden(fn (Get $get): bool => $get('role') !== 'staff')

In this example, the role field is set to live(), which means that the schema will reload the schema each time the role field is changed. This will cause the function that is passed to the hidden() method to be re-evaluated, which will hide the is_admin field if the role field is not set to staff.

However, reloading the schema each time a field causes a network request to be made, since there is no way to re-run the PHP function from the client-side. This is not ideal for performance.

Alternatively, you can write JavaScript to hide the field based on the value of another field. This is done by passing a JavaScript expression to the hiddenJs() method:

use Filament\Forms\Components\Select;
use Filament\Forms\Components\Toggle;

Select::make('role')
    ->options([
        'user' => 'User',
        'staff' => 'Staff',
    ])

Toggle::make('is_admin')
    ->hiddenJs(<<<'JS'
        $get('role') !== 'staff'
        JS)

Although the code passed to hiddenJs() looks very similar to PHP, it is actually JavaScript. Filament provides the $get() utility function to JavaScript that behaves very similar to its PHP equivalent, but without requiring the depended-on field to be live().

The visibleJs() method is also available, which works in the same way as hiddenJs(), but controls if the field should be visible or not:

use Filament\Forms\Components\Select;
use Filament\Forms\Components\Toggle;

Select::make('role')
    ->options([
        'user' => 'User',
        'staff' => 'Staff',
    ])

Toggle::make('is_admin')
    ->visibleJs(<<<'JS'
        $get('role') === 'staff'
        JS)

Hiding a field based on the current operation

The "operation" of a schema is the current action being performed on it. Usually, this is either create, edit or view, if you are using the panel resource.

You can hide a field based on the current operation by passing an operation to the hiddenOn() method:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->hiddenOn('edit')
    
// is the same as

Toggle::make('is_admin')
    ->hidden(fn (string $operation): bool => $operation === 'edit')

You can also pass an array of operations to the hiddenOn() method, and the field will be hidden if the current operation is any of the operations in the array:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->hiddenOn(['edit', 'view'])
    
// is the same as

Toggle::make('is_admin')
    ->hidden(fn (string $operation): bool => in_array($operation, ['edit', 'view']))

Alternatively, you may use the visibleOn() method to control if the field should be hidden or not. In some situations, this may help to make your code more readable:

use Filament\Forms\Components\Toggle;

Toggle::make('is_admin')
    ->visibleOn('create')

Toggle::make('is_admin')
    ->visibleOn(['create', 'edit'])

Inline labels

Fields may have their labels displayed inline with the field, rather than above it. This is useful for forms with many fields, where vertical space is at a premium. To display a field's label inline, use the inlineLabel() method:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->inlineLabel()

Optionally, you may pass a boolean value to control if the label should be displayed inline or not:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->inlineLabel(FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the inlineLabel() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Using inline labels in multiple places at once

If you wish to display all labels inline in a layout component like a section or tab, you can use the inlineLabel() on the component itself, and all fields within it will have their labels displayed inline:

use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;

Section::make('Details')
    ->inlineLabel()
    ->schema([
        TextInput::make('name'),
        TextInput::make('email')
            ->label('Email address'),
        TextInput::make('phone')
            ->label('Phone number'),
    ])

You can also use inlineLabel() on the entire schema to display all labels inline:

use Filament\Schemas\Schema;

public function form(Schema $schema): Schema
{
    return $schema
        ->inlineLabel()
        ->components([
            // ...
        ]);
}

When using inlineLabel() on a layout component or schema, you can still opt-out of inline labels for individual fields by using the inlineLabel(false) method on the field:

use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\Section;

Section::make('Details')
    ->inlineLabel()
    ->schema([
        TextInput::make('name'),
        TextInput::make('email')
            ->label('Email address'),
        TextInput::make('phone')
            ->label('Phone number')
            ->inlineLabel(false),
    ])

Autofocusing a field when the schema is loaded

Most fields are autofocusable. Typically, you should aim for the first significant field in your schema to be autofocused for the best user experience. You can nominate a field to be autofocused using the autofocus() method:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->autofocus()

Optionally, you may pass a boolean value to control if the field should be autofocused or not:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->autofocus(FeatureFlag::active())

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the autofocus() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Setting the placeholder of a field

Many fields can display a placeholder for when they have no value. This is displayed in the UI but never saved when the form is submitted. You may customize this placeholder using the placeholder() method:

use Filament\Forms\Components\TextInput;

TextInput::make('name')
    ->placeholder('John Doe')

<UtilityInjection set="formFields" version="5.x">As well as allowing a static value, the placeholder() method also accepts a function to dynamically calculate it. You can inject various utilities into the function as parameters.</UtilityInjection>

Fusing fields together into a group

A FusedGroup component can be used to "fuse" multiple fields together. The following fields can be fused together the best:

The fields that should be fused are passed to the make() method of the FusedGroup component:

use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\FusedGroup;

FusedGroup::make([
    TextInput::make('city')
        ->placeholder('City'),
    Select::make('country')
        ->placeholder('Country')
        ->options([
            // ...
        ]),
])

You can add a label above the group of fields using the label() method:

use Filament\Schemas\Components\FusedGroup;

FusedGroup::make([
    // ...
])
    ->label('Location')

By default, each field will have its own row. On mobile devices, this is often the most optimal experience, but on desktop you can use the columns() method, the same as for layout components to display the fields horizontally:

use Filament\Schemas\Components\FusedGroup;

FusedGroup::make([
    // ...
])
    ->label('Location')
    ->columns(2)

You can adjust the width of the fields in the grid by passing columnSpan() to each field:

use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Schemas\Components\FusedGroup;

FusedGroup::make([
    TextInput::make('city')
        ->placeholder('City')
        ->columnSpan(2),
    Select::make('country')
        ->placeholder('Country')
        ->options([
            // ...
        ]),
])
    ->label('Location')
    ->columns(3)

Adding extra content to a field

Fields contain many "slots" where content can be inserted in a child schema. Slots can accept text, any schema component, actions and action groups. Usually, prime components are used for content.

The following slots are available for all fields:

  • aboveLabel()
  • beforeLabel()
  • afterLabel()
  • belowLabel()
  • aboveContent()
  • beforeContent()
  • afterContent()
  • belowContent()
  • aboveErrorMessage()
  • belowErrorMessage()

<UtilityInjection set="formFields" version="5.x">As well as allowing static values, the slot methods also accept functions to dynamically calculate them. You can inject various utilities into the functions as parameters.</UtilityInjection>

To...

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4