Skip to main content
Custom Fields comes with 20+ built-in field types and allows you to create your own custom field types for specialized functionality.

Built-in Field Types

Custom Fields includes 20+ pre-configured field types:
Field TypeKeyData TypeDescription
Text InputtextStringBasic text input with validation
EmailemailStringEmail input with validation
PhonephoneStringPhone number input
LinklinkStringURL validation and formatting
TextareatextareaTextMulti-line text input
Rich Editorrich-editorTextWYSIWYG editor with formatting
Markdown Editormarkdown-editorTextMarkdown syntax with preview
NumbernumberNumericNumeric input with min/max validation
CurrencycurrencyFloatCurrency formatting with locale support
Tags Inputtags-inputMulti-choiceMultiple tags with autocomplete
SelectselectSingle-choiceSingle selection dropdown
Multi-Selectmulti-selectMulti-choiceMultiple selections
RadioradioSingle-choiceSingle choice radio buttons
CheckboxcheckboxBooleanSimple true/false toggle
Checkbox Listcheckbox-listMulti-choiceMultiple checkboxes
ToggletoggleBooleanSwitch-style toggle
Toggle Buttonstoggle-buttonsSingle-choiceButton group selection
DatedateDateDate picker
Date TimedatetimeDateTimeDate and time picker
Color Pickercolor-pickerStringVisual color selection
File Uploadfile-uploadStringFile upload with validation

Creating Custom Field Types

You have flexible options for extending Custom Fields:
  • Create entirely new field types for specialized functionality
  • Extend existing built-in field types to add custom behavior
  • Replace built-in field types by creating custom ones with the same key
This allows you to customize any field type behavior while maintaining compatibility with the existing system.

Generate a Field Type

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/.

Field Type Structure

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 Field Type

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,
                    ]),
            ]);
    }
}

Extending and Replacing Field Types

You have additional flexibility with custom field types:
  • Replace built-in field types: Create a custom field type with the same key as a built-in type (e.g., file-upload) to completely override it with your own implementation and behavior
This allows you to customize or completely replace any built-in field type behavior while maintaining system compatibility.

FieldSchema API

The FieldSchema class provides a fluent API for configuring field types. Choose the appropriate factory method based on your field’s data type:

Data Type Factory Methods

// 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

Configuration Methods

->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

Component Types

You can define components in two ways:

1. Class References (Simple)

For basic components, reference Filament classes directly:
->formComponent(TextInput::class)
->tableColumn(TextColumn::class)
->infolistEntry(TextEntry::class)

2. Closures (Flexible)

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 and Options

Choice fields (select, radio, checkboxes) can handle options in different ways:

User-Defined Options (Default)

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
    });

Built-in Options

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',
            ]);
    });

Arbitrary Values

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());
    });

Data Types

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
}

Best Practices

  1. Use Existing Filament Components: Build on Filament’s components like Select, TextInput, etc.
  2. Follow Naming Conventions: Use kebab-case for keys (e.g., star-rating, country-select)
  3. Choose the Right Data Type: Select the data type that matches how your field’s values should be stored
  4. Use Closures for Flexibility: For complex components, use closure-based definitions
  5. Test Your Components: Ensure your field type works in forms, tables, and infolists
  6. Consider Validation: Only allow validation rules that make sense for your field type

Field Type Priority

Field types are ordered by priority (lower numbers appear first):
  • 10-20: Common text fields
  • 30-40: Selection fields
  • 50-60: Specialized fields
  • 70+: Advanced fields

Troubleshooting

Field Type Not Appearing

If your custom field type doesn’t appear in the dropdown:
  1. Ensure your field type class extends BaseFieldType
  2. Verify the field type is registered in your panel provider
  3. Clear Laravel’s cache: php artisan cache:clear
  4. Check that the configure() method returns a valid FieldSchema

Components Not Rendering

If your components don’t render correctly:
  1. Verify you’re using $customField->getFieldName() for field names
  2. For closure-based components, ensure closures return valid Filament components
  3. Test with simple components first before adding complexity
  4. Check that you’re importing all necessary Filament component classes
Your custom field type will now appear in the field type dropdown when creating new custom fields!