Custom Fields comes with 20+ built-in field types and allows you to create your own custom field types for specialized functionality.
Custom Fields includes 20+ pre-configured field types:
| Field Type | Key | Data Type | Description |
|---|---|---|---|
| Text Input | text | String | Basic text input with validation |
email | String | Email input with validation | |
| Phone | phone | String | Phone number input |
| Link | link | String | URL validation and formatting |
| Textarea | textarea | Text | Multi-line text input |
| Rich Editor | rich-editor | Text | WYSIWYG editor with formatting |
| Markdown Editor | markdown-editor | Text | Markdown syntax with preview |
| Number | number | Numeric | Numeric input with min/max validation |
| Currency | currency | Float | Currency formatting with locale support |
| Tags Input | tags-input | Multi-choice | Multiple tags with autocomplete |
| Select | select | Single-choice | Single selection dropdown |
| Multi-Select | multi-select | Multi-choice | Multiple selections |
| Radio | radio | Single-choice | Single choice radio buttons |
| Checkbox | checkbox | Boolean | Simple true/false toggle |
| Checkbox List | checkbox-list | Multi-choice | Multiple checkboxes |
| Toggle | toggle | Boolean | Switch-style toggle |
| Toggle Buttons | toggle-buttons | Single-choice | Button group selection |
| Date | date | Date | Date picker |
| Date Time | date-time | DateTime | Date and time picker |
| Color Picker | color-picker | String | Visual color selection |
| File Upload | file-upload | String | File upload with validation |
| Record | record | Multi-choice | Polymorphic model lookup |
You have flexible options for extending Custom Fields:
This allows you to customize any field type behavior while maintaining compatibility with the existing system.
Use the Artisan command to create a new field type:
php artisan make:field-type StarRating
This creates a complete field type class in app/Filament/FieldTypes/.
Custom field types extend BaseFieldType and use the FieldSchema system:
<?php
namespace App\Filament\FieldTypes;
use Filament\Forms\Components\Select;
use Filament\Infolists\Components\TextEntry;
use Filament\Tables\Columns\TextColumn;
use Relaticle\CustomFields\Enums\ValidationRule;
use Relaticle\CustomFields\FieldTypeSystem\BaseFieldType;
use Relaticle\CustomFields\FieldTypeSystem\FieldSchema;
use Relaticle\CustomFields\Models\CustomField;
class StarRatingFieldType extends BaseFieldType
{
public function configure(): FieldSchema
{
return FieldSchema::numeric()
->key('star-rating')
->label('Star Rating')
->icon('heroicon-o-star')
->formComponent(function (CustomField $customField) {
return Select::make($customField->getFieldName())
->options([
1 => '⭐ Poor',
2 => '⭐⭐ Fair',
3 => '⭐⭐⭐ Good',
4 => '⭐⭐⭐⭐ Very Good',
5 => '⭐⭐⭐⭐⭐ Excellent',
])
->native(false);
})
->tableColumn(function (CustomField $customField) {
return TextColumn::make($customField->getFieldName())
->formatStateUsing(function ($state) {
if (!$state) return 'No rating';
return str_repeat('⭐', (int) $state) . " ($state/5)";
});
})
->infolistEntry(function (CustomField $customField) {
return TextEntry::make($customField->getFieldName())
->formatStateUsing(function ($state) {
if (!$state) return 'No rating provided';
$rating = (int) $state;
$labels = [1 => 'Poor', 2 => 'Fair', 3 => 'Good', 4 => 'Very Good', 5 => 'Excellent'];
return str_repeat('⭐', $rating) . " - {$labels[$rating]} ($rating/5)";
});
})
->priority(45)
->availableValidationRules([
ValidationRule::REQUIRED,
ValidationRule::MIN,
ValidationRule::MAX,
]);
}
}
Register your custom field type in your Filament Panel Provider:
<?php
namespace App\Providers\Filament;
use App\Filament\FieldTypes\StarRatingFieldType;
use Filament\Panel;
use Filament\PanelProvider;
use Relaticle\CustomFields\CustomFieldsPlugin;
class AdminPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->plugins([
CustomFieldsPlugin::make()
->registerFieldTypes([
StarRatingFieldType::class,
]),
]);
}
}
You have additional flexibility with custom field types:
file-upload) to completely override it with your own implementation and behaviorThis allows you to customize or completely replace any built-in field type behavior while maintaining system compatibility.
The FieldSchema class provides a fluent API for configuring field types. Choose the appropriate factory method based on your field's data type:
// Text-based fields
FieldSchema::text() // For TEXT data type (long text)
FieldSchema::string() // For STRING data type (short text)
// Numeric fields
FieldSchema::numeric() // For NUMERIC data type (integers)
FieldSchema::float() // For FLOAT data type (decimals)
// Date/time fields
FieldSchema::date() // For DATE data type
FieldSchema::dateTime() // For DATE_TIME data type
// Boolean fields
FieldSchema::boolean() // For BOOLEAN data type
// Choice fields
FieldSchema::singleChoice() // For SINGLE_CHOICE data type
FieldSchema::multiChoice() // For MULTI_CHOICE data type
->key('field-key') // Unique field identifier
->label('Field Label') // Display name
->icon('heroicon-o-star') // Icon for field type
->priority(50) // Sort order (lower = first)
->formComponent($component) // Form field component
->tableColumn($column) // Table column component
->infolistEntry($entry) // Read-only display component
->availableValidationRules($rules) // User-selectable validation rules
->defaultValidationRules($rules) // Always-applied validation rules
->searchable() // Enable table search
->sortable() // Enable table sorting
->filterable() // Enable table filtering
->encryptable() // Allow field encryption
You can define components in two ways:
For basic components, reference Filament classes directly:
->formComponent(TextInput::class)
->tableColumn(TextColumn::class)
->infolistEntry(TextEntry::class)
For customized components, use closures that return configured components:
->formComponent(function (CustomField $customField) {
return TextInput::make($customField->getFieldName())
->label($customField->name)
->maxLength(255);
})
Choice fields (select, radio, checkboxes) can handle options in different ways:
Users define their own options when creating fields:
return FieldSchema::singleChoice()
->key('priority-level')
->formComponent(function (CustomField $customField) {
return Select::make($customField->getFieldName());
// Options automatically applied by the system
});
Field type provides predefined options:
return FieldSchema::singleChoice()
->key('priority-level')
->withoutUserOptions() // Disable user options
->formComponent(function (CustomField $customField) {
return Select::make($customField->getFieldName())
->options([
1 => 'Low',
2 => 'Medium',
3 => 'High',
4 => 'Critical',
]);
});
Accept both predefined and new user-typed values:
return FieldSchema::multiChoice()
->key('product-tags')
->withArbitraryValues() // Allow new values
->formComponent(function (CustomField $customField) {
return TagsInput::make($customField->getFieldName());
});
Custom Fields supports these data types for storage optimization and validation compatibility:
enum FieldDataType: string
{
case STRING = 'string'; // Short text, URLs, identifiers
case TEXT = 'text'; // Long text, rich content, markdown
case NUMERIC = 'numeric'; // Integers, counts
case FLOAT = 'float'; // Decimal numbers, currency
case DATE = 'date'; // Date only
case DATE_TIME = 'date_time'; // Date with time
case BOOLEAN = 'boolean'; // True/false, checkboxes, toggles
case SINGLE_CHOICE = 'single_choice'; // Select, radio buttons
case MULTI_CHOICE = 'multi_choice'; // Multi-select, checkbox lists, tags
}
Select, TextInput, etc.star-rating, country-select)Field types are ordered by priority (lower numbers appear first):
If your custom field type doesn't appear in the dropdown:
BaseFieldTypephp artisan cache:clearconfigure() method returns a valid FieldSchemaIf your components don't render correctly:
$customField->getFieldName() for field namesYour custom field type will now appear in the field type dropdown when creating new custom fields!