ngx-material-intl-tel-input
Version:
Angular Material international telephone input
506 lines (499 loc) • 19 kB
TypeScript
import * as _angular_core from '@angular/core';
import { OnInit, AfterViewInit, OnDestroy, ElementRef } from '@angular/core';
import { FormControl, FormGroup, AbstractControl } from '@angular/forms';
import { MatSelect } from '@angular/material/select';
import { ReplaySubject, Subject } from 'rxjs';
import { PhoneNumberUtil, PhoneNumberFormat } from 'google-libphonenumber';
import { MatFormFieldAppearance } from '@angular/material/form-field';
declare enum CountryISO {
Afghanistan = "af",
Albania = "al",
Algeria = "dz",
AmericanSamoa = "as",
Andorra = "ad",
Angola = "ao",
Anguilla = "ai",
AntiguaAndBarbuda = "ag",
Argentina = "ar",
Armenia = "am",
Aruba = "aw",
Australia = "au",
Austria = "at",
Azerbaijan = "az",
Bahamas = "bs",
Bahrain = "bh",
Bangladesh = "bd",
Barbados = "bb",
Belarus = "by",
Belgium = "be",
Belize = "bz",
Benin = "bj",
Bermuda = "bm",
Bhutan = "bt",
Bolivia = "bo",
BosniaAndHerzegovina = "ba",
Botswana = "bw",
Brazil = "br",
BritishIndianOceanTerritory = "io",
BritishVirginIslands = "vg",
Brunei = "bn",
Bulgaria = "bg",
BurkinaFaso = "bf",
Burundi = "bi",
Cambodia = "kh",
Cameroon = "cm",
Canada = "ca",
CapeVerde = "cv",
CaribbeanNetherlands = "bq",
CaymanIslands = "ky",
CentralAfricanRepublic = "cf",
Chad = "td",
Chile = "cl",
China = "cn",
ChristmasIsland = "cx",
Cocos = "cc",
Colombia = "co",
Comoros = "km",
CongoDRCJamhuriYaKidemokrasiaYaKongo = "cd",
CongoRepublicCongoBrazzaville = "cg",
CookIslands = "ck",
CostaRica = "cr",
CôteDIvoire = "ci",
Croatia = "hr",
Cuba = "cu",
Curaçao = "cw",
Cyprus = "cy",
CzechRepublic = "cz",
Denmark = "dk",
Djibouti = "dj",
Dominica = "dm",
DominicanRepublic = "do",
Ecuador = "ec",
Egypt = "eg",
ElSalvador = "sv",
EquatorialGuinea = "gq",
Eritrea = "er",
Estonia = "ee",
Ethiopia = "et",
FalklandIslands = "fk",
FaroeIslands = "fo",
Fiji = "fj",
Finland = "fi",
France = "fr",
FrenchGuiana = "gf",
FrenchPolynesia = "pf",
Gabon = "ga",
Gambia = "gm",
Georgia = "ge",
Germany = "de",
Ghana = "gh",
Gibraltar = "gi",
Greece = "gr",
Greenland = "gl",
Grenada = "gd",
Guadeloupe = "gp",
Guam = "gu",
Guatemala = "gt",
Guernsey = "gg",
Guinea = "gn",
GuineaBissau = "gw",
Guyana = "gy",
Haiti = "ht",
Honduras = "hn",
HongKong = "hk",
Hungary = "hu",
Iceland = "is",
India = "in",
Indonesia = "id",
Iran = "ir",
Iraq = "iq",
Ireland = "ie",
IsleOfMan = "im",
Israel = "il",
Italy = "it",
Jamaica = "jm",
Japan = "jp",
Jersey = "je",
Jordan = "jo",
Kazakhstan = "kz",
Kenya = "ke",
Kiribati = "ki",
Kosovo = "xk",
Kuwait = "kw",
Kyrgyzstan = "kg",
Laos = "la",
Latvia = "lv",
Lebanon = "lb",
Lesotho = "ls",
Liberia = "lr",
Libya = "ly",
Liechtenstein = "li",
Lithuania = "lt",
Luxembourg = "lu",
Macau = "mo",
Macedonia = "mk",
Madagascar = "mg",
Malawi = "mw",
Malaysia = "my",
Maldives = "mv",
Mali = "ml",
Malta = "mt",
MarshallIslands = "mh",
Martinique = "mq",
Mauritania = "mr",
Mauritius = "mu",
Mayotte = "yt",
Mexico = "mx",
Micronesia = "fm",
Moldova = "md",
Monaco = "mc",
Mongolia = "mn",
Montenegro = "me",
Montserrat = "ms",
Morocco = "ma",
Mozambique = "mz",
Myanmar = "mm",
Namibia = "na",
Nauru = "nr",
Nepal = "np",
Netherlands = "nl",
NewCaledonia = "nc",
NewZealand = "nz",
Nicaragua = "ni",
Niger = "ne",
Nigeria = "ng",
Niue = "nu",
NorfolkIsland = "nf",
NorthKorea = "kp",
NorthernMarianaIslands = "mp",
Norway = "no",
Oman = "om",
Pakistan = "pk",
Palau = "pw",
Palestine = "ps",
Panama = "pa",
PapuaNewGuinea = "pg",
Paraguay = "py",
Peru = "pe",
Philippines = "ph",
Poland = "pl",
Portugal = "pt",
PuertoRico = "pr",
Qatar = "qa",
Réunion = "re",
Romania = "ro",
Russia = "ru",
Rwanda = "rw",
SaintBarthélemy = "bl",
SaintHelena = "sh",
SaintKittsAndNevis = "kn",
SaintLucia = "lc",
SaintMartin = "mf",
SaintPierreAndMiquelon = "pm",
SaintVincentAndTheGrenadines = "vc",
Samoa = "ws",
SanMarino = "sm",
SãoToméAndPríncipe = "st",
SaudiArabia = "sa",
Senegal = "sn",
Serbia = "rs",
Seychelles = "sc",
SierraLeone = "sl",
Singapore = "sg",
SintMaarten = "sx",
Slovakia = "sk",
Slovenia = "si",
SolomonIslands = "sb",
Somalia = "so",
SouthAfrica = "za",
SouthKorea = "kr",
SouthSudan = "ss",
Spain = "es",
SriLanka = "lk",
Sudan = "sd",
Suriname = "sr",
SvalbardAndJanMayen = "sj",
Swaziland = "sz",
Sweden = "se",
Switzerland = "ch",
Syria = "sy",
Taiwan = "tw",
Tajikistan = "tj",
Tanzania = "tz",
Thailand = "th",
TimorLeste = "tl",
Togo = "tg",
Tokelau = "tk",
Tonga = "to",
TrinidadAndTobago = "tt",
Tunisia = "tn",
Turkey = "tr",
Turkmenistan = "tm",
TurksAndCaicosIslands = "tc",
Tuvalu = "tv",
USVirginIslands = "vi",
Uganda = "ug",
Ukraine = "ua",
UnitedArabEmirates = "ae",
UnitedKingdom = "gb",
UnitedStates = "us",
Uruguay = "uy",
Uzbekistan = "uz",
Vanuatu = "vu",
VaticanCity = "va",
Venezuela = "ve",
Vietnam = "vn",
WallisAndFutuna = "wf",
WesternSahara = "eh",
Yemen = "ye",
Zambia = "zm",
Zimbabwe = "zw",
ÅlandIslands = "ax"
}
type Country = {
emojiFlag: string;
name: string;
iso2: CountryISO | string;
dialCode: string;
priority: number;
areaCodes?: string[];
htmlId: string;
flagClass: string;
placeHolder: string;
mask?: {
mask: string;
lazy?: boolean;
};
};
type TextLabels = {
mainLabel: string;
codePlaceholder: string;
searchPlaceholderLabel: string;
noEntriesFoundLabel: string;
nationalNumberLabel: string;
hintLabel: string;
invalidNumberError: string;
requiredError: string;
numberTooLongError?: string;
};
declare class NgxMaterialIntlTelInputComponent implements OnInit, AfterViewInit, OnDestroy {
private readonly countryCodeData;
private readonly geoIpService;
private readonly countryDataService;
private readonly controlContainer;
/** control for the selected country prefix */
prefixCtrl: FormControl<Country | null>;
/** control for the MatSelect filter keyword */
prefixFilterCtrl: FormControl<string | null>;
/** list of countries filtered by search keyword */
filteredCountries: ReplaySubject<Country[]>;
singleSelect: _angular_core.Signal<MatSelect | undefined>;
numberInput: _angular_core.Signal<ElementRef<any> | undefined>;
/** Subject that emits when the component has been destroyed. */
protected _onDestroy: Subject<void>;
allCountries: Country[];
phoneNumberUtil: PhoneNumberUtil;
telForm: FormGroup<{
prefixCtrl: FormControl<Country | null>;
numberControl: FormControl<string | null>;
}>;
fieldControl: _angular_core.ModelSignal<AbstractControl<string | null, string | null, any> | FormControl<any> | null>;
fieldControlName: _angular_core.InputSignal<string>;
required: _angular_core.ModelSignal<boolean>;
disabled: _angular_core.ModelSignal<boolean>;
appearance: _angular_core.InputSignal<MatFormFieldAppearance>;
enablePlaceholder: _angular_core.InputSignal<boolean>;
autoIpLookup: _angular_core.InputSignal<boolean>;
autoSelectCountry: _angular_core.InputSignal<boolean>;
autoSelectedCountry: _angular_core.InputSignal<string>;
numberValidation: _angular_core.InputSignal<boolean>;
iconMakeCall: _angular_core.InputSignal<boolean>;
initialValue: _angular_core.ModelSignal<string>;
enableSearch: _angular_core.InputSignal<boolean>;
includeDialCode: _angular_core.InputSignal<boolean>;
emojiFlags: _angular_core.InputSignal<boolean>;
hidePhoneIcon: _angular_core.InputSignal<boolean>;
preferredCountries: _angular_core.InputSignal<string[]>;
visibleCountries: _angular_core.InputSignal<string[]>;
excludedCountries: _angular_core.InputSignal<string[]>;
textLabels: _angular_core.InputSignal<TextLabels>;
mainLabel: _angular_core.InputSignal<string>;
useMask: _angular_core.InputSignal<boolean>;
forceSelectedCountryCode: _angular_core.InputSignal<boolean>;
showMaskPlaceholder: _angular_core.InputSignal<boolean>;
outputNumberFormat: _angular_core.InputSignal<PhoneNumberFormat.E164 | PhoneNumberFormat.INTERNATIONAL | PhoneNumberFormat.RFC3966>;
enableInputMaxLength: _angular_core.InputSignal<boolean>;
currentValue: _angular_core.OutputEmitterRef<string>;
currentCountryCode: _angular_core.OutputEmitterRef<string>;
currentCountryISO: _angular_core.OutputEmitterRef<string>;
isFocused: _angular_core.WritableSignal<boolean>;
isLoading: _angular_core.WritableSignal<boolean>;
constructor();
/**
* Initialize the component and perform necessary setup tasks.
*
*/
ngOnInit(): void;
/**
* Fetches country data and populates the allCountries array.
*/
protected fetchCountryData(): void;
/**
* Adds validations to the form field based on the current configuration.
* It sets required validators and disabled state, and if number validation is enabled,
* it adds a custom validator to check the validity of the phone number.
*/
private addValidations;
/**
* Sets the required validators for the field control based on the 'required' input property.
* If 'required' is true, adds a 'Validators.required' validator to the field control.
* If 'required' is false, removes the 'Validators.required' validator from the field control.
*/
setRequiredValidators(): void;
/**
* Sets the disabled state of the telForm and fieldControl based on the 'disabled' input property.
* If 'disabled' is true, both telForm and fieldControl are disabled.
* If 'disabled' is false, both telForm and fieldControl are enabled.
*/
setDisabledState(): void;
/**
* A lifecycle hook that is called after Angular has fully initialized a component's view.
*
* @return {void}
*/
ngAfterViewInit(): void;
/**
* Method called when the component is destroyed.
*
*/
ngOnDestroy(): void;
/**
* Performs a geo IP lookup and sets the prefix control value based on the country retrieved.
*/
private geoIpLookup;
/**
* Sets the initial value after the filteredCountries are loaded initially
*/
protected setInitialPrefixValue(): void;
/**
* Method to filter the list of countries based on a search keyword.
*
*/
protected filterCountries(): void;
/**
* A method that handles the focus event for the input.
*
*/
onInputFocus(): void;
/**
* A method that handles the blur event for the input.
*/
onInputBlur(): void;
/**
* Listens for changes in the telForm value and updates the fieldControl accordingly.
*/
private startTelFormValueChangesListener;
/**
* Listens for changes in the prefix control value and updates the number control accordingly.
* If includeDialCode is true and the data contains a dialCode, sets the number control value with the dial code.
* If isLoading is false, focuses on the number input element after a timeout.
*/
private startPrefixValueChangesListener;
/**
* Sets the initial telephone value based on the initial value.
*/
private setInitialTelValue;
/**
* Set the auto selected country based on the specified criteria.
*
*/
private setAutoSelectedCountry;
/**
* Listens to changes in the field control value and updates it accordingly.
* If the value is valid, it parses and formats it using the phoneNumberUtil.
* If the value is not valid, it sets the value as is.
* Finally, emits the currentValue signal with the updated field control value.
*/
private startFieldControlValueChangesListener;
/**
* Listens to changes in the status of the field control and updates the 'disabled' model accordingly.
* If the status is 'DISABLED', sets the 'disabled' model to true; otherwise, sets it to false.
*/
private startFieldControlStatusChangesListener;
/**
* Sets the field control based on the provided field control name.
* If the field control name exists in the control container, it sets the field control to that value.
* Additionally, it checks for the initial value, required validator, and disabled state of the field control.
*/
private setFieldControl;
/**
* Sets the cursor position in the input element after formatting the phone number.
*
* @param inputElement - The HTML input element where the cursor position is to be set.
* @param cursorPosition - The current cursor position in the input element.
* @param parsed - The parsed phone number object.
* @param currentValue - The current value of the input element.
*/
private setCursorPosition;
/**
* Adjusts the cursor position in an input field after a value change,
* accounting for added or removed spaces in the new value.
*
* @param originalPosition - The original cursor position before the value change.
* @param oldValue - The previous value of the input field.
* @param newValue - The new value of the input field.
* @returns The adjusted cursor position, ensuring it remains within valid bounds.
*/
private adjustCursorPosition;
/**
* Counts the number of spaces in a string before a specified position.
*
* @param value - The string to be evaluated.
* @param position - The position in the string up to which spaces are counted.
* @returns The number of spaces found before the specified position.
*/
private countSpacesBeforePosition;
/**
* Gets the maximum input length for a given country code.
* This is used to set the maxlength attribute on the input field.
* Dynamically adjusts based on whether the current number is valid/formatted.
*
* @param countryCode ISO2 country code
* @returns Maximum allowed length for the input field
*/
getMaxInputLength: (countryCode?: string) => number;
/**
* Checks if the current number is valid and properly formatted.
* Valid formatted numbers contain spaces/separators.
*
* @param currentValue Current input value
* @param countryCode ISO2 country code
* @returns True if number is valid and formatted
*/
private isCurrentNumberValidAndFormatted;
/**
* Calculates an appropriate safety margin based on component configuration.
* Different configurations require different buffer spaces.
* Uses conservative margins to prevent overly long input that requires JS correction.
*
* @returns Calculated safety margin
*/
private calculateSafetyMargin;
/**
* Calculates the formatting buffer needed for a country's phone number formatting.
* Analyzes example formatted numbers to determine space requirements.
*
* @param countryCode ISO2 country code
* @param baseLength Base maximum number length
* @returns Calculated formatting buffer
*/
private calculateFormattingBuffer;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<NgxMaterialIntlTelInputComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<NgxMaterialIntlTelInputComponent, "ngx-material-intl-tel-input", never, { "fieldControl": { "alias": "fieldControl"; "required": false; "isSignal": true; }; "fieldControlName": { "alias": "fieldControlName"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "appearance": { "alias": "appearance"; "required": false; "isSignal": true; }; "enablePlaceholder": { "alias": "enablePlaceholder"; "required": false; "isSignal": true; }; "autoIpLookup": { "alias": "autoIpLookup"; "required": false; "isSignal": true; }; "autoSelectCountry": { "alias": "autoSelectCountry"; "required": false; "isSignal": true; }; "autoSelectedCountry": { "alias": "autoSelectedCountry"; "required": false; "isSignal": true; }; "numberValidation": { "alias": "numberValidation"; "required": false; "isSignal": true; }; "iconMakeCall": { "alias": "iconMakeCall"; "required": false; "isSignal": true; }; "initialValue": { "alias": "initialValue"; "required": false; "isSignal": true; }; "enableSearch": { "alias": "enableSearch"; "required": false; "isSignal": true; }; "includeDialCode": { "alias": "includeDialCode"; "required": false; "isSignal": true; }; "emojiFlags": { "alias": "emojiFlags"; "required": false; "isSignal": true; }; "hidePhoneIcon": { "alias": "hidePhoneIcon"; "required": false; "isSignal": true; }; "preferredCountries": { "alias": "preferredCountries"; "required": false; "isSignal": true; }; "visibleCountries": { "alias": "visibleCountries"; "required": false; "isSignal": true; }; "excludedCountries": { "alias": "excludedCountries"; "required": false; "isSignal": true; }; "textLabels": { "alias": "textLabels"; "required": false; "isSignal": true; }; "mainLabel": { "alias": "mainLabel"; "required": false; "isSignal": true; }; "useMask": { "alias": "useMask"; "required": false; "isSignal": true; }; "forceSelectedCountryCode": { "alias": "forceSelectedCountryCode"; "required": false; "isSignal": true; }; "showMaskPlaceholder": { "alias": "showMaskPlaceholder"; "required": false; "isSignal": true; }; "outputNumberFormat": { "alias": "outputNumberFormat"; "required": false; "isSignal": true; }; "enableInputMaxLength": { "alias": "enableInputMaxLength"; "required": false; "isSignal": true; }; }, { "fieldControl": "fieldControlChange"; "required": "requiredChange"; "disabled": "disabledChange"; "initialValue": "initialValueChange"; "currentValue": "currentValue"; "currentCountryCode": "currentCountryCode"; "currentCountryISO": "currentCountryISO"; }, never, never, true, never>;
}
declare class PhoneIconComponent {
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PhoneIconComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PhoneIconComponent, "ngx-material-intl-tel-input-phone-icon", never, {}, {}, never, never, true, never>;
}
export { CountryISO, NgxMaterialIntlTelInputComponent, PhoneIconComponent };
export type { TextLabels };