Phone input
It does not validate

It formats and joins the number. It does not check that the number is valid for the country.

A country button and a number field

Wrap an .input-group with an input[type=tel] in .phone-input. data-country sets the first country and data-name names the hidden input that holds the number the form sends.

Pick a country, or type + and a dial code.

A full number in the field picks the country

A value that starts with + and a dial code sets the country and leaves the national part in the field. This works for a value set in the markup, for typing and for paste.

The form sends the joined number

Spaces, dashes and brackets are dropped. For countries that use a leading trunk 0 (such as Thailand and the UK) it is dropped too. tsunami:phonechange fires when the country or the number changes.

+66812345678

Invalid, disabled and sizes

aria-invalid="true" and disabled go on the input[type=tel]. data-size goes on the .input-group.

Enter the full number.

Behavior

  • The button opens a list of countries with a search box. Search by name, ISO code or dial code.
  • Country names come from Intl.DisplayNames in the page language (html lang). The list holds about 240 countries and adds about 8 KB to tsunami.min.js.
  • Typing + and a dial code switches the country as soon as a digit follows the code. The longest dial code wins, so +1 242 is the Bahamas and +1 415 is the US. For a number that shares the +1 code, paste it whole or pick the country from the list.
  • The hidden input holds +, the dial code and the digits of the field, or an empty string while the field is empty. The visible text is never rewritten, except to remove a dial code you typed.
  • The trunk 0 is dropped only for a fixed list of countries where it is always a trunk prefix. For any other country the digits are joined as typed.
  • It does not validate. It does not check length, area codes or number type, so use your server or a library for that.
  • The field has autocomplete="tel-national" unless you set another value. A form reset puts back the first country and the original text.

API

It starts every .phone-input on the page, also one added later.

Methods

MethodDescription
tsunami.phoneInput.get(el)Returns { country, dial, number, value } for a .phone-input or an element inside it.
tsunami.phoneInput.set(el, v)Sets the field. v is a string ("+66812345678", or national digits for the current country) or { country, number }. It fires the events below.

Events

EventOnDescription
tsunami:phonechange.phone-input, bubblesThe country or the number changed. detail is { country, dial, number, value }: country is the ISO code ("TH"), dial is "+66", number is the digits sent after it and value is the whole number ("+66812345678", or "" when empty).
input, changethe hidden input, bubblesSent when the country or number changes, so a form or the save bar hears it. Typing also sends the native events from the input[type=tel].

Keyboard

KeyDescription
Enter, Space, ↓On the country button, opens the list and moves focus to the search box.
↓, ↑, Home, EndIn the search box, move through the countries.
EnterPicks the highlighted country and returns to the number field.
EscCloses the list.

Attributes

AttributeOnDescription
data-country.phone-inputISO 3166 code of the first country, such as TH. Default US. It follows the picked country.
data-name.phone-inputName of the hidden input that holds the international number. Without it nothing is sent.
disabledinput[type=tel]Disables the number field, the country button and the hidden input.
aria-invalid="true"input[type=tel]Draws the danger border on the group.
data-size="sm|lg".input-groupMatches the input sizes.

Accessibility

  • The country button is named Country: Thailand +66 and opens a listbox. The search box is a combobox that points to the highlighted option with aria-activedescendant.
  • Label the input[type=tel] with a label. Flags are decorative and hidden from assistive technology.