Skip to content

<flux:phone> displays the national trunk prefix in the number input #2834

Description

@electronick86

Flux version

v2.20.0

Livewire version

v4.4.2

Tailwind version

v4.1.11

Browser and Operating System

Safari on macOS

What is the problem?

Summary

<flux:phone> displays the national trunk prefix in the number input even though the dial code is already shown separately in the country picker. For countries that have a trunk prefix (Belgium, France, the UK, the Netherlands…), the control reads as a number that does not exist.

For a Belgian mobile, the control renders:

[ 🇧🇪 +32 ▾ ] [ 0470 12 34 56 ]

Read as a whole that is +32 0470 12 34 56, which is not dialable. The 0 is the national trunk prefix and is mutually exclusive with the +32 shown to its left.

Expected behaviour

When the dial code is displayed separately, the input should hold the national significant number without the trunk prefix:

[ 🇧🇪 +32 ▾ ] [ 470 12 34 56 ]

Reproduction

<flux:phone country="BE" label="Phone number" />

Type 470123456, or bind an existing +32470123456. The input formats to 0470 12 34 56.

Same with country="FR" (leading 0), country="GB" (leading 0), country="NL" (leading 0). Countries without a trunk prefix, such as US, are unaffected — which is probably why it went unnoticed.

Root cause

vendor/livewire/flux-pro/dist/phone.js, in ui-phone's mount() (around line 5367):

this.iti = intlTelInput_default(this.inputEl, {
    initialCountry: this.getAttribute("country")?.toLowerCase() || "",
    onlyCountries: csvAttribute(this, "countries"),
    countryOrder: csvAttribute(this, "country-order"),
    countrySelectorMode: "OFF",
    showFlags: false,
    separateDialCode: false,   // <-- but Flux does show the dial code separately
    numberDisplayFormat: "NATIONAL",
    formatAsYouType: true,
    strictMode: false,
    loadUtils: () => import(this.getAttribute("utils-url") || "./phone-utils.js")
});

Flux renders its own country picker (the +32 button) but tells intl-tel-input that the dial code is not separate. That disables the two safeguards the library has for exactly this case:

  1. Line ~2284 — the option normaliser, which would have switched the display format away from NATIONAL:
if (o.separateDialCode && o.numberDisplayFormat === NUMBER_FORMAT.NATIONAL) {
    o.numberDisplayFormat = NUMBER_FORMAT.INTERNATIONAL;
}
  1. Line ~4357 — the trunk prefix strip:
const hasPrefix = nationalPrefix && number.startsWith(nationalPrefix) && !this.#options.separateDialCode;

Both are gated on separateDialCode, so with the flag set to false the prefix survives into the visible value.

Suggested fix

Pass separateDialCode: true (and let the library normalise numberDisplayFormat itself), or keep separateDialCode: false and set numberDisplayFormat: "INTERNATIONAL" while stripping the dial code Flux already renders in its own button.

Not affected

The bound value is correct — getValue() delegates to iti.getNumber(), which returns proper E.164 (+32470123456, no 0). This is a display-only defect, but a confusing one in a product where users check the number they are reachable on.

Code snippets to replicate the problem

<flux:phone country="BE" label="Phone number" />

Screenshots/ screen recordings of the problem

Image

Please confirm (incomplete submissions will not be addressed)

  • I have provided easy and step-by-step instructions to reproduce the bug.
  • I have provided code samples as text and NOT images.
  • I understand my bug report will be closed if I haven't met the criteria above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions