Skip to main content
PhoneField ← Back to Table of Contents

Summary

International phone input with searchable country picker, libphonenumber validation, and structured state (country, national, e164).
ClassBjanczak\FilamentFlexFields\Filament\Forms\Components\PhoneField
State typearray<country: string, national: string, e164: string>
FieldTypephone

Basic usage

use Bjanczak\FilamentFlexFields\Filament\Forms\Components\PhoneField;

PhoneField::make('phone')
    ->label('Mobile number')
    ->defaultCountry('PL')
    ->required();

PhoneField::make('contact_phone')
    ->countries(['PL', 'DE', 'GB', 'US'])
    ->mobileOnly()
    ->browserLocaleDefault()
    ->browserLocaleSortFirst();
Load from an E.164 string on edit:
PhoneField::make('phone')
    ->afterStateHydrated(function (PhoneField $component, mixed $state): void {
        if (is_string($state) && filled($state)) {
            $component->state($component->normalizeState($state));
        }
    });
Store only E.164 in the database:
PhoneField::make('phone')
    ->dehydrateStateUsing(fn (array $state): ?string => filled($state['e164'] ?? null)
        ? $state['e164']
        : null);

State format

KeyDescriptionExample
countryISO 3166-1 alpha-2 region codePL
nationalNational number digits only512345678
e164E.164 format when valid+48512345678
On hydrate and dehydrate, normalizeState() runs automatically. A plain string state (e.g. +48 512 345 678) is parsed on hydrate.

Validation

BehaviourDetail
Built-inCustom rule on normalized array; uses libphonenumber
required()national must not be empty
mobileOnly()Number type must be mobile (or fixed-line-or-mobile)
fixedLineOnly()Number type must be fixed line (or fixed-line-or-mobile)
Filament required ruleOverridden to nullable — validation handled by custom rule
Do not combine mobileOnly() and fixedLineOnly() on the same field — throws InvalidArgumentException.

Configuration API

variant(string|Closure $variant)

Visual style shared with FlexTextInput. Values: primary (default), secondary, flat.
->variant('secondary')

size(string|ControlSize|Closure $size)

Control height. See Control size. Default: md.
PhoneField::make('field_name')
    ->size('md');

defaultCountry(string|Closure $countryCode)

ISO country code when no country is selected. Default: PL. Falls back to first allowed country or US.
PhoneField::make('field_name')
    ->defaultCountry('value');

countries(array|Closure|null $countries)

Whitelist of ISO codes. null = all countries (minus exceptCountries).
->countries(['PL', 'DE', 'FR'])

exceptCountries(array|Closure $countries)

Blacklist applied after the whitelist. Default: [].
PhoneField::make('field_name')
    ->exceptCountries(['value1', 'value2']);

searchable(bool|Closure $condition = true)

Show search input in the country dropdown. Default: true.
PhoneField::make('field_name')
    ->searchable(true);

suffixIcon(string|BackedEnum|Htmlable|Closure|bool|null $icon = null)

Trailing icon. Pass false to hide. Pass an icon name to set a custom icon. Default: config filament-flex-fields.ui.phone_suffix_icon or GravityIcon::Smartphone.
->suffixIcon(false)
->suffixIcon('heroicon-o-device-phone-mobile')

internationalPrefix(bool|Closure $condition = true)

Show dial code prefix next to the national input. Default: true.
PhoneField::make('field_name')
    ->internationalPrefix(true);

mobileOnly(bool|Closure $condition = true)

Restrict to mobile numbers.
PhoneField::make('field_name')
    ->mobileOnly(true);

fixedLineOnly(bool|Closure $condition = true)

Restrict to fixed-line numbers.
PhoneField::make('field_name')
    ->fixedLineOnly(true);

browserLocaleDefault(bool|Closure $condition = true)

When enabled and national number is empty, pre-select country from Accept-Language / browser locale.
PhoneField::make('field_name')
    ->browserLocaleDefault(true);

browserLocaleSortFirst(bool|Closure $condition = true)

Sort country list with browser locale country first.
PhoneField::make('field_name')
    ->browserLocaleSortFirst(true);

placeholder(string|Closure|null $placeholder)

Inherited from Filament HasPlaceholder.
PhoneField::make('field_name')
    ->placeholder('Enter value...');

readOnly(bool|Closure $condition = true)

Inherited from Filament CanBeReadOnly.
PhoneField::make('field_name')
    ->readOnly(true);

focusOutline(bool|Closure $condition = true)

Inherited from HasFieldFocusOutline.
PhoneField::make('field_name')
    ->focusOutline(true);

Public helper methods

MethodReturnsDescription
getVariant()stringResolved variant
getAllowedCountryCodes()list<string>|nullWhitelist or null
getExceptCountryCodes()list<string>Blacklist
getDefaultCountryCode()stringEffective default region
isSearchable()boolCountry search enabled
hasSuffixIcon()boolSuffix icon visible
showsInternationalPrefix()boolDial prefix visible
isMobileOnly()boolMobile validation
isFixedLineOnly()boolFixed-line validation
shouldUseBrowserLocaleDefault()boolBrowser locale default
shouldSortCountriesByBrowserLocale()boolBrowser locale sort
getBrowserLocaleCountryCode()string|nullDetected locale country
getCountriesMetadata()list<array>code, name, dial_code, flag_url
getCountrySelectOptions()arrayOptions for internal select
getDefaultSuffixIcon()string|BackedEnum|HtmlableDefault suffix icon
getSuffixIcon()string|BackedEnum|Htmlable|nullResolved suffix icon
normalizeState(mixed $state)arrayCanonical {country, national, e164}
getPhoneValidationMessage(array $state)string|nullError message or null
getWrapperClasses()list<string>CSS class list

FlexField schema config

Config keyMaps to
sizesize()
variantvariant()
default_countrydefaultCountry()
countriescountries()
except_countriesexceptCountries()
searchablesearchable()
suffix_iconsuffixIcon()
international_prefixinternationalPrefix()
mobile_onlymobileOnly()
fixed_line_onlyfixedLineOnly()
browser_locale_defaultbrowserLocaleDefault()
browser_locale_sort_firstbrowserLocaleSortFirst()

CSS classes

ClassRole
fff-phone-fieldRoot wrapper
fff-phone-field--{sm|md|lg}Size modifier
fff-phone-field__country-triggerCountry picker button
fff-phone-field__country-menuTeleported dropdown (is-positioned when open)
fff-phone-field__controlNational number input area
fff-phone-field__dial-prefixInternational prefix display
Shares FlexTextInput shell classes (fff-flex-text-input-field, variant modifiers).

Implementation notes

  • Country dropdown uses x-teleport="body" to avoid overflow clipping.
  • Depends on giggsey/libphonenumber-for-php for parsing and validation.
  • Empty national number dehydrates to e164: '' regardless of partial dial prefix.