Introduction
Filament provides a powerful foundation for creating custom form fields. By extending the baseField class, you can build reusable field components that integrate seamlessly with Filament’s form system, including validation, state management, and Livewire integration.
Understanding the Field base class
All form fields in Filament extend theField class located at packages/forms/src/Components/Field.php. This base class provides:
- State management and binding
- Validation integration
- Label, helper text, and hint functionality
- Required field marking
- Autofocus capabilities
- Integration with Filament’s schema system
Creating a basic custom field
use Filament\Forms\Components\Field;
class ColorPicker extends Field
{
protected string $view = 'filament.forms.components.color-picker';
}
Create the corresponding Blade view at
resources/views/filament/forms/components/color-picker.blade.php:<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<input
type="color"
{{ $getExtraInputAttributeBag()->class(['fi-input']) }}
{{ $applyStateBindingModifiers('wire:model') }}="{{ $getStatePath() }}"
@if ($isDisabled())
disabled
@endif
/>
</x-dynamic-component>
Adding custom methods
You can add custom configuration methods to your field using the fluent API pattern:Using concerns for reusable functionality
Filament uses traits (concerns) to add reusable functionality. You can use existing concerns or create your own:Implementing validation
Custom fields can add validation rules using therule() method:
Working with state casts
State casts transform data between the form and database. You can implement custom state casts:Advanced example: Rich text editor integration
Here’s a more complex example integrating a third-party JavaScript library:Accessing the Livewire component
You can access the parent Livewire component and interact with it:Registering custom fields globally
You can register custom fields as macros to make them available on all field instances:Best practices
- Always extend the
Fieldbase class for full integration - Use the
evaluate()method to support closures in configuration - Follow Filament’s naming conventions: use
is/should/can/hasprefixes for boolean properties - Implement the
setUp()method for default configuration - Use concerns (traits) for reusable functionality
- Never use
finalclasses - allow users to extend your fields - Use
app()instead ofnewfor dependency resolution to allow binding custom implementations - Add comprehensive PHPDoc annotations for arrays and complex types