Skip to main content
← Back to Table of Contents

Summary

International phone input with searchable country picker, local circle flags, libphonenumber validation, and structured state (country, national, e164).

Basic usage

Load from an E.164 string on edit:
Store only E.164 in the database:
To store the default composite value, use a JSON column with an Eloquent array cast. Its country key is a code such as PL or DE, never the country label. Country names, flag URLs and dropdown descriptions are not persisted. Saving only E.164 is optional, using the dehydration callback above.

State format

On hydrate and dehydrate, normalizeState() runs automatically. A plain string state (e.g. +48 512 345 678) is parsed on hydrate. Default national stays NATIONAL-formatted for BC; use digits-only or e164 when you need machine-friendly values.

Validation

Do not combine mobileOnly() and fixedLineOnly() on the same field — throws InvalidArgumentException. Prefer allowTypes() for multi-type rules.

Configuration API

variant(string|Closure $variant)

Visual style shared with FlexTextInput. Values: primary (default), secondary, flat, soft.

size(string|ControlSize|Closure $size)

Control height. See Control size. Default: md.

defaultCountry(string|Closure $countryCode)

ISO country code when no country is selected. Default: PL. Falls back to first allowed country or US.

countries(array|Closure|null $countries)

Whitelist of ISO codes. null = all countries (minus exceptCountries).

exceptCountries(array|Closure $countries)

Blacklist applied after the whitelist. Default: [].

searchable(bool|Closure $condition = true)

Show search input in the country dropdown. Default: 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.

internationalPrefix(bool|Closure $condition = true)

Show dial code prefix next to the national input. Default: true.

mobileOnly(bool|Closure $condition = true)

Restrict to mobile numbers.

fixedLineOnly(bool|Closure $condition = true)

Restrict to fixed-line numbers.

browserLocaleDefault(bool|Closure $condition = true)

When enabled and national number is empty, pre-select country from Accept-Language / browser locale.

browserLocaleSortFirst(bool|Closure $condition = true)

Sort country list with browser locale country first.

locale(string|Closure|null $locale)

Language for country names in the picker (en → Poland, pl → Polska). Defaults to app()->getLocale(). CountryField and PhoneField share the same translation resolver: package overrides first, then PHP ICU regional names, then English fallback. Names are identical on the initial render and in the dropdown.

placeholder(string|Closure|null $placeholder)

Inherited from Filament HasPlaceholder. When omitted, the field uses a libphonenumber national example for the default country (and mobile/fixed type when constrained), otherwise the package language string.

allowTypes(array|Closure|null $types)

Restrict accepted libphonenumber number types (PhoneNumberType cases or names like MOBILE, VOIP). When set, overrides mobileOnly() / fixedLineOnly() sugar.

strictTypes(bool|Closure $condition = true)

Do not auto-accept FIXED_LINE_OR_MOBILE alongside MOBILE / FIXED_LINE.

validateForRegion(bool|Closure $condition = true)

Require isValidNumberForRegion() for the selected country (stricter than global isValidNumber).

nationalFormat(PhoneNationalFormat|string|Closure $format) / nationalDigitsOnly()

Default national (BC). Digits-only is opt-in:

includeFormats(array|Closure $formats)

Add international and/or rfc3966 keys to dehydrated state (valid numbers only).

includeMetadata(array|Closure $metadata)

Add PHP-side carrier, geo, timezones, and/or type keys (valid numbers only). No JS / phone-lib budget impact.

readOnly(bool|Closure $condition = true)

Inherited from Filament CanBeReadOnly.

focusOutline(bool|Closure $condition = true)

Inherited from HasFieldFocusOutline.

Public helper methods

FlexField schema config

CSS classes

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.

Playground

Slug: phone-field /admin/flex-fields/phone-field — see Playground.

Country catalog and local flags

The country picker follows libphonenumber’s supported telephone regions, including AC, TA and XK. It is intentionally separate from CountryField’s default 249-entry ISO address catalog: some ISO territories do not have a supported calling-code region. The exact telephone list follows the installed libphonenumber metadata version. countries() and exceptCountries() constrain both selection and locale detection. Both pickers share one country-flags asset publication. All supported flags are materialized local SVG files, including territories whose upstream files are aliases. No external flag CDN is contacted. Publish them through the standard installation steps:
See Installation for deployment and asset checks. Country names and metadata are cached within the request; no browser-side country-name library or full flag preloading is required. The current installed libphonenumber metadata contains 245 telephone regions, while CountryField defaults to 249 ISO entries. Telephone regions are not a superset of the address catalog. Every supported region has a local flag and a calling prefix from libphonenumber, including shared prefixes such as +1. The prefix displayed by PhoneField follows the selected region.

Submitted state and server validation

Save through Filament’s validated getState() result. Validation rejects unknown or excluded region codes, country labels, structured country values, non-string national numbers, unsupported characters and excessive input. Malformed state can be rendered safely without raising a server error, but cannot pass validation. required() also rejects an empty national number. The server derives E.164 from country and national; a forged client-side e164 cannot override it. Unrequested keys such as labels, flag URLs or enrichment are removed on dehydration. Enabled includeFormats() / includeMetadata() values are computed on the server and retained; submitted enrichment is never trusted. validateForRegion() additionally requires the parsed number to be valid for the selected region. This remains optional because several regions share calling codes.
Last modified on October 16, 2026