Skip to content

Phone field in a form

<telixon-phone-field> turns the <input> inside it into a phone field. Once the engine has loaded, the element attaches a PhoneInput of @telixon/web-sdk to the input, the widget that formats the text and tracks the region. From then on the field is live. The element is form-associated. The form submits its value in E.164 under the element’s name and validates it like a native field, while the input itself carries no name.

The attributes mode, default-region, calling-code-in-input, plus-prefix, strict, region-filter, number-type-filter, and placeholder-number-type configure the widget. The reference lists each with its default. An element without any of them runs in international mode with the calling code inside the input. The value attribute gives the field its first number.

<telixon-phone-field name="phone" default-region="US" calling-code-in-input="false" value="+14155550132">
<input type="tel" autocomplete="tel" />
</telixon-phone-field>

Typing 4155550132 into an empty field of this shape shows 415-555-0132. The same digits show (415) 555-0132 in a field with mode="national". With the calling code inside the input and plus-prefix="fixed", they show +1 415-555-0132.

The options property takes the whole options object, which a framework binds in one expression. A set object replaces the attributes as a whole. null hands the options back to the attributes:

field.options = { mode: 'international', defaultRegion: 'US', display: { callingCodeInInput: false } };

A change of the options keeps or replaces the widget as the reference describes.

The value property holds the number in E.164 while the number is valid and null at any other time. The telixon-change event fires whenever that value changes through an edit or through new options, with the value in event.detail.value:

field.addEventListener('telixon-change', (event) => {
console.log(event.detail.value); // "+14155550132"
});

A written value shows in the input the way the field formats numbers. With the calling code outside the input, +442071838750 shows as 20 7183 8750 with the United Kingdom as the region. In a national field the same value shows as 020 7183 8750. With the calling code inside the input it shows as 44 20 7183 8750. A write fires no telixon-change, since the page already knows the value. '' clears the field.

field.value = '+442071838750';

The state property holds the widget’s latest state, which carries the region and the text. phone holds the widget itself. Both are null until the field is live.

A partial number blocks the form’s submission the way an invalid native field does, with a message anchored at the input. The fault property holds the ValidationError behind it:

field.fault; // { kind: 'TOO_SHORT', minLength: 10 }
field.validationMessage; // "This number is too short."

A field without digits reports no fault. required makes it report valueMissing, as the reference describes. checkValidity() and reportValidity() work as on a native field.

The error-message attribute replaces the message for every fault. The errorMessage property takes a function from the fault to its message, which can give each fault its own text:

field.errorMessage = (fault) => (fault.kind === 'TOO_SHORT' ? 'Add the missing digits.' : 'Check the number.');

Without either, the element uses an English message for each fault, which the reference lists.

The element exposes its validity through custom states, which match through :state(). invalid follows every keystroke, while user-invalid waits until the field is touched, which makes it the state to color a border with:

telixon-phone-field:state(user-invalid) input {
border-color: #e5484d;
}
telixon-phone-field:state(engine-loading) input {
opacity: 0.7;
}

The element and the picker are inline by default. The stylesheet of the example lays the form out in a column, puts the picker and the input side by side, and colors the border of a field the user left invalid:

styles.css
#contact {
display: grid;
gap: 0.75rem;
max-width: 24rem;
}
#contact telixon-phone-field {
display: flex;
gap: 0.5rem;
}
#contact input {
flex: 1;
padding: 0.5em 0.75em;
border: 1px solid #c4c7c5;
border-radius: 0.375rem;
background: transparent;
color: inherit;
font: inherit;
}
#contact telixon-phone-field:state(user-invalid) input {
border-color: #e5484d;
}
#contact button {
justify-self: start;
padding: 0.5em 1em;
border: 1px solid #c4c7c5;
border-radius: 0.375rem;
background: transparent;
color: inherit;
font: inherit;
cursor: pointer;
}
#contact p {
margin: 0;
}

The picker takes ::part() rules and the --tlx-picker-* custom properties, as the picker guide shows.

A <label for> points at the input, which takes focus. type="tel" shows the phone keypad on iOS and Android. autocomplete="tel" lets the browser fill the number from the user’s profile, which the field reads against its region. Keep the input’s font size at 16 px or larger, because iOS Safari zooms into a smaller field on focus.

required, disabled, and readonly belong on the element. The element mirrors disabled and readonly onto the input and keeps a disabled or readonly the page put on the input itself. The auto-placeholder attribute shows an example number for the region, 201-555-0123 for the United States with the calling code outside the input.