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.
Installation
composer require filament/forms
Publish the package’s assets (if needed) and config:
php artisan vendor:publish --provider="Filament\Forms\FormsServiceProvider"
Basic Usage
Create a Livewire component and use the Form facade or trait:
use Filament\Forms\Form;
use Livewire\Component;
class MyFormComponent extends Component
{
public function mount()
{
Form::make()
->schema([
\Filament\Forms\Components\TextInput::make('name'),
]);
}
}
First Form in a View
Use the filamentForms directive in your Blade template:
<livewire:my-form-component />
@livewireScripts
Form Facade/Traits – Core class for building forms.Components Namespace – Pre-built form fields (e.g., TextInput, Select, Checkbox).Dynamic Schema Build forms programmatically based on user roles or data:
public function form()
{
return Form::make()
->schema([
TextInput::make('email')
->required()
->email(),
Select::make('role')
->options(['admin', 'user'])
->visible(fn () => auth()->user()->isAdmin()),
]);
}
Validation & Submission
Handle form submission with Livewire’s rules() and save():
use Illuminate\Support\Facades\Validator;
public function rules()
{
return [
'name' => 'required|max:255',
];
}
public function save()
{
$validated = $this->validate();
// Process data...
}
Reusable Form Components Extract form logic into a dedicated class:
class UserProfileForm
{
public static function make()
{
return Form::make()
->schema([
TextInput::make('bio')->columnSpanFull(),
]);
}
}
Integration with Filament Admin Use in Filament panels for CRUD operations:
use Filament\Forms\Components\TextInput;
public static function form(Form $form): Form
{
return $form
->schema([
TextInput::make('title')->required(),
]);
}
mounted(), updated(), and render() to sync form state.$data property for form persistence.Filament\Forms\Components\Field for domain-specific inputs.Schema Caching
public function form()
{
return cache()->remember('form_schema', now()->addHours(1), function () {
return Form::make()->schema([...]);
});
}
Livewire State Conflicts
$name vs. name field).->key() to disambiguate:
TextInput::make('name')->key('user_name')
Asset Loading
filamentForms directive is included after @livewireScripts in Blade templates.$errors in Livewire’s render() or use dd($this->validate()).->visible(fn () => true) to test logic.->afterStateUpdated(fn () => Log::info('Updated')) for debugging.Custom Fields
Extend Filament\Forms\Components\Field:
class CustomField extends Field
{
protected string $view = 'filament.forms.custom-field';
}
Form Modifiers
Use ->modifyQueryUsing() or ->modifyOptionsUsing() for dynamic data:
Select::make('country')
->options(fn () => Country::pluck('name', 'id'))
->modifyQueryUsing(fn (Builder $query) => $query->whereActive(true))
Localization
Override labels/placeholders via config or ->label()/->placeholder():
TextInput::make('name')->label(__('filament::forms.fields.name'))
Testing
Use Form::make()->fill() to simulate submissions:
$form = Form::make()->schema([...]);
$form->fill(['name' => 'Test']);
$this->assertEquals('Test', $form->getState()['name']);
How can I help you explore Laravel packages today?