Skip to content

Build the complete field

This guide wires the phone field and the region picker into one widget, where the picker supplies the calling code and the input holds the rest. The flag sprite draws the flags.

Open the picker, search canada, and pick it. The button shows the Canadian flag and +1. The placeholder switches to a Canadian example number. Type 6045550132 and the field shows 604-555-0132 with the status Valid: +16045550132. Reopen the picker and choose United States. 604 still belongs to Canada, which flips the flag straight back.

Undo reaches the picker as well. Cmd/Ctrl+Z steps back through the digits, then through the region change itself, carrying the flag and the calling code with it. Cmd/Ctrl+Shift+Z replays the whole sequence.

Search united k and press Enter, or walk the rows with the arrow keys. Select the United Kingdom and type 07400123456. The leading zero is the UK trunk prefix and does not belong after +44. The status reads NATIONAL_PREFIX_PRESENT.

The demo and the source are the same three files. The markup is the region button with a flag cell, the input, a popup with the search box and the list, and a status line.

The script creates three widgets. createRegionList builds the rows with US, CA, and GB pinned on top. createPhoneInput binds the input with callingCodeInInput: false, which keeps the calling code out of the field and leaves it to the selected region. createRegionPicker takes both. From then on the phone owns the region. A pick calls the phone’s setRegion. The picker follows the phone’s resolved region back and moves the flag when the digits land in another region on the same calling code.

The attachRegionPicker call matches Build a region picker, except that renderTrigger writes the calling code next to the flag and returnFocusTo sends focus to the input after a pick.

The demo positions the popup itself. positionPopup flips it above the field when there is no room below. renderStatus draws the placeholder and the status from each emitted state.

When a framework component unmounts, call destroy on the attachment and on each widget.

<div id="complete-field" class="phone-field">
<label for="phone-field-input">Phone number</label>
<div class="phone-field-control">
<button class="phone-field-region" aria-label="Select region">
<span class="tlx-flag" aria-hidden="true"><span class="tlx-flag__image"></span></span>
<span class="phone-field-code"></span>
<svg class="phone-field-chevron" viewBox="0 0 10 6" aria-hidden="true">
<path d="M1 1l4 4 4-4" fill="none" stroke="currentColor" stroke-width="1.5" />
</svg>
</button>
<input id="phone-field-input" type="tel" />
</div>
<div class="phone-field-menu" hidden>
<input class="phone-field-search" type="text" aria-label="Search regions" placeholder="Search regions" />
<ul aria-label="Regions"></ul>
</div>
<p class="phone-field-status"></p>
</div>