Country-aware phone value and validation builder. Your application owns the country picker and input UI.
- For a basic phone text input without country metadata, use
field.tel()instead - Build a web/native
PhoneFieldfromform.fieldController(name)and your country data storeE164()normalizes the output to+33612345678format for API consumption
Defaults, inheritance & field methods
- defaultValue is
null - type is
phone - placeholder defaults to
'Enter phone number' - debounce defaults to
0for immediate formatting feedback - default country is
'FR', preferred countries default to['FR', 'US', 'GB', 'DE', 'ES'] - Shared methods: see Base field builder
Phone-specific methods:
| Method | Type | Description |
|---|---|---|
defaultCountry(code) | code: string | Sets the initial selected country. |
preferredCountries(codes) | codes: string[] | Stores the preferred-country configuration for a country-aware phone experience. |
searchable(value = true) | value?: boolean | Stores whether the application-owned country picker should offer search. |
showFlag(value = true) | value?: boolean | Shows or hides the country flag. |
showDialCode(value = true) | value?: boolean | Shows or hides the dial code prefix. |
countryLayout(layout) | 'integrated' | 'detached' | Describes whether your country selector should sit inside the input shell (integrated, default) or as a separate control (detached). |
storeE164() | () => this | Stores a normalized E.164 string (e.g. +33612345678) instead of the richer { country, national, e164 } phone payload. Use this when the backend expects a flat string. |
validateFormat(value = true) | value?: boolean | Enables libphonenumber-based format validation. Adds three sequential checks: isPossible(), isValid(), and a format parse - each with its own error message. Disable with validateFormat(false) if you need lenient input. |
Render a country-aware input
FormBridge no longer renders a country picker. Keep the schema responsible for the phone value, required state, E.164 storage, and format validation; keep flags, country search, modal/popover behavior, and styling in an application-owned PhoneField.
The interactive examples above use a small local country list. In production, that list can come from your localization layer or phone-input package. Forward the resulting E.164 string to controller.onChange() when using storeE164(). Without storeE164(), forward the PhoneValue shape expected by the schema.
Recipes
Patterns that showcase phone-specific strengths.
International signup
| 1 | const schema = { |
| 2 | phone: field.phone('Phone') |
| 3 | .defaultCountry('FR') |
| 4 | .preferredCountries(['FR', 'US', 'GB']) |
| 5 | .searchable() |
| 6 | .showFlag(true) |
| 7 | .showDialCode(true), |
| 8 | } |
API-ready E.164 output
| 1 | const schema = { |
| 2 | phone: field.phone('Phone') |
| 3 | .storeE164() |
| 4 | .required() |
| 5 | .validateFormat(true), |
| 6 | } |
US-only customer support
| 1 | const schema = { |
| 2 | phone: field.phone('Phone') |
| 3 | .defaultCountry('US') |
| 4 | .preferredCountries(['US']) |
| 5 | .showDialCode(false) |
| 6 | .validateFormat(), |
| 7 | } |
Disabled display field
| 1 | const schema = { |
| 2 | supportLine: field.phone('Support line') |
| 3 | .defaultCountry('US') |
| 4 | .disabled() |
| 5 | .hint('Managed by your account team'), |
| 6 | } |