@intl-ui/angular
v1.0.3
Published
Angular components and directives for international UI: phone input, country selector. Signal-based, standalone, accessible.
Maintainers
Readme
@intl-ui/angular
Angular components and directives for international phone input. Signal-based, standalone, accessible.
Part of the @intl-ui ecosystem.
Install
npm install @intl-ui/angular
# or
pnpm add @intl-ui/angular
# or
yarn add @intl-ui/angularPeer dependencies: @angular/core and @angular/forms (v17+).
Quick start
import { Component, signal } from '@angular/core';
import { IntlPhoneInputComponent } from '@intl-ui/angular';
@Component({
standalone: true,
imports: [IntlPhoneInputComponent],
template: `
<intl-phone-input [defaultCountry]="'co'" [(value)]="phone" />
<p>E.164: {{ phone() }}</p>
`,
})
export class AppComponent {
phone = signal('');
}That's it. See it running in the live demo.
Usage
1. Standalone component (quickest)
import { Component, signal } from '@angular/core';
import { IntlPhoneInputComponent } from '@intl-ui/angular';
@Component({
standalone: true,
imports: [IntlPhoneInputComponent],
template: `
<intl-phone-input
[defaultCountry]="'us'"
[(value)]="phone"
(phoneChange)="onPhoneChange($event)"
/>
`,
})
export class MyComponent {
phone = signal('');
onPhoneChange(meta) {
console.log(meta.isValid, meta.parsed?.e164);
}
}2. Reactive Forms (ControlValueAccessor)
import { Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import {
IntlPhoneInputComponent,
IntlPhoneInputValueAccessorDirective,
IntlPhoneValidators,
} from '@intl-ui/angular';
@Component({
standalone: true,
imports: [
ReactiveFormsModule,
IntlPhoneInputComponent,
IntlPhoneInputValueAccessorDirective,
],
template: `
<form [formGroup]="form">
<intl-phone-input formControlName="phone" [defaultCountry]="'co'" />
</form>
`,
})
export class MyFormComponent {
form = new FormGroup({
phone: new FormControl('', [
Validators.required,
IntlPhoneValidators.validPhone(),
]),
});
}3. Headless store (full control)
import { Component } from '@angular/core';
import { createPhoneInputStore, type CountryIso2 } from '@intl-ui/angular';
@Component({
standalone: true,
template: `
<button (click)="store.toggleDropdown()">
{{ store.country()?.flag ?? 'Pick' }}
</button>
<input
type="tel"
[value]="store.inputValue()"
(input)="onInput($event)"
/>
<p>E.164: {{ store.value() }}</p>
<p>Valid: {{ store.isValid() }}</p>
`,
})
export class HeadlessComponent {
store = createPhoneInputStore({ initialCountry: 'gb' as CountryIso2 });
onInput(event: Event) {
this.store.handleInput((event.target as HTMLInputElement).value);
}
}API
IntlPhoneInputComponent
| Input | Type | Default | Description |
|-------|------|---------|-------------|
| defaultCountry | CountryIso2 | - | Initial country ISO2 code |
| defaultValue | string | '' | Initial phone value (E.164) |
| disableCountryGuess | boolean | false | Disable auto-detection from digits |
| countries | Country[] | all | Custom country list |
| preferredCountries | CountryIso2[] | [] | Pin countries to top |
| showSearch | boolean | true | Show search in dropdown |
| Output | Type | Description |
|--------|------|-------------|
| value | model<string> | Two-way binding for E.164 value |
| phoneChange | ValueChangeMeta | Emits on every value change |
| countryChange | Country | Emits when country changes |
IntlPhoneValidators
| Validator | Description |
|-----------|-------------|
| validPhone(country?) | Validates phone format (optionally for a specific country) |
| allowedCountries(iso2[]) | Restricts to specific countries |
createPhoneInputStore(options)
Signal-based store for building custom UIs. Returns signals for value, inputValue, country, parsed, isValid, isOpen, visibleCountries, and action methods.
Bundle size
| Package | gzip |
|---------|------|
| @intl-ui/core | ~9.4 KB |
| @intl-ui/angular | ~18 KB |
| Total | ~27 KB |
Related
@intl-ui/core— Framework-agnostic data & utilities@intl-ui/react— React hooks & components
