ngx-mat-input-tel
Version:
An Angular Material package for entering and validating international telephone numbers. It adds a flag dropdown to any input, detects the user's country, displays a relevant placeholder and provides formatting/validation methods.
949 lines (945 loc) • 173 kB
JavaScript
import * as i1 from '@angular/cdk/a11y';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { NgClass } from '@angular/common';
import * as i0 from '@angular/core';
import { Pipe, EventEmitter, signal, booleanAttribute, Output, Input, HostBinding, ViewChild, Optional, Self, ChangeDetectionStrategy, Component } from '@angular/core';
import * as i2 from '@angular/forms';
import { FormsModule, ReactiveFormsModule, NG_VALIDATORS } from '@angular/forms';
import * as i3 from '@angular/material/core';
import { MatRippleModule } from '@angular/material/core';
import * as i6 from '@angular/material/divider';
import { MatDividerModule } from '@angular/material/divider';
import { MatFormFieldControl } from '@angular/material/form-field';
import * as i4 from '@angular/material/input';
import { MatInputModule } from '@angular/material/input';
import * as i5 from '@angular/material/menu';
import { MatMenuModule, MatMenu } from '@angular/material/menu';
import { parsePhoneNumber, parsePhoneNumberFromString, getExampleNumber, AsYouType } from 'libphonenumber-js';
import { Subject } from 'rxjs';
const ALL_COUNTRIES = [
// 'name', 'iso2', 'dialCode', 'priority', 'areaCodes'
['Afghanistan (افغانستان)', 'af', '93'],
['Albania (Shqipëri)', 'al', '355'],
['Algeria (الجزائر)', 'dz', '213'],
['American Samoa', 'as', '1', 4, ['684']],
['Andorra', 'ad', '376'],
['Angola', 'ao', '244'],
['Anguilla', 'ai', '1', 4, ['264']],
['Antigua and Barbuda', 'ag', '1', 4, ['268']],
['Argentina', 'ar', '54'],
['Armenia (Հայաստան)', 'am', '374'],
['Aruba', 'aw', '297'],
['Australia', 'au', '61', 0],
['Austria (Österreich)', 'at', '43'],
['Azerbaijan (Azərbaycan)', 'az', '994'],
['Bahamas', 'bs', '1', 4, ['242']],
['Bahrain (البحرين)', 'bh', '973'],
['Bangladesh (বাংলাদেশ)', 'bd', '880'],
['Barbados', 'bb', '1', 4, ['246']],
['Belarus (Беларусь)', 'by', '375'],
['Belgium (België)', 'be', '32'],
['Belize', 'bz', '501'],
['Benin (Bénin)', 'bj', '229'],
['Bermuda', 'bm', '1', 4, ['441']],
['Bhutan (འབྲུག)', 'bt', '975'],
['Bolivia', 'bo', '591'],
['Bosnia and Herzegovina (Босна и Херцеговина)', 'ba', '387'],
['Botswana', 'bw', '267'],
['Brazil (Brasil)', 'br', '55'],
['British Indian Ocean Territory', 'io', '246'],
['British Virgin Islands', 'vg', '1', 4, ['284']],
['Brunei', 'bn', '673'],
['Bulgaria (България)', 'bg', '359'],
['Burkina Faso', 'bf', '226'],
['Burundi (Uburundi)', 'bi', '257'],
['Cambodia (កម្ពុជា)', 'kh', '855'],
['Cameroon (Cameroun)', 'cm', '237'],
[
'Canada',
'ca',
'1',
1,
[
'204',
'226',
'236',
'249',
'250',
'289',
'306',
'343',
'365',
'387',
'403',
'416',
'418',
'431',
'437',
'438',
'450',
'506',
'514',
'519',
'548',
'579',
'581',
'587',
'604',
'613',
'639',
'647',
'672',
'705',
'709',
'742',
'778',
'780',
'782',
'807',
'819',
'825',
'867',
'873',
'902',
'905',
],
],
['Cape Verde (Kabu Verdi)', 'cv', '238'],
['Caribbean Netherlands', 'bq', '599', 1],
['Cayman Islands', 'ky', '1', 4, ['345']],
['Central African Republic (République centrafricaine)', 'cf', '236'],
['Chad (Tchad)', 'td', '235'],
['Chile', 'cl', '56'],
['China (中国)', 'cn', '86'],
['Christmas Island', 'cx', '61', 2],
['Cocos (Keeling) Islands', 'cc', '61', 1],
['Colombia', 'co', '57'],
['Comoros (جزر القمر)', 'km', '269'],
['Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)', 'cd', '243'],
['Congo (Republic) (Congo-Brazzaville)', 'cg', '242'],
['Cook Islands', 'ck', '682'],
['Costa Rica', 'cr', '506'],
['Côte d’Ivoire', 'ci', '225'],
['Croatia (Hrvatska)', 'hr', '385'],
['Cuba', 'cu', '53'],
['Curaçao', 'cw', '599', 0],
['Cyprus (Κύπρος)', 'cy', '357'],
['Czech Republic (Česká republika)', 'cz', '420'],
['Denmark (Danmark)', 'dk', '45'],
['Djibouti', 'dj', '253'],
['Dominica', 'dm', '1', 4, ['767']],
['Dominican Republic (República Dominicana)', 'do', '1', 2, ['809', '829', '849']],
['Ecuador', 'ec', '593'],
['Egypt (مصر)', 'eg', '20'],
['El Salvador', 'sv', '503'],
['Equatorial Guinea (Guinea Ecuatorial)', 'gq', '240'],
['Eritrea', 'er', '291'],
['Estonia (Eesti)', 'ee', '372'],
['Ethiopia', 'et', '251'],
['Falkland Islands (Islas Malvinas)', 'fk', '500'],
['Faroe Islands (Føroyar)', 'fo', '298'],
['Fiji', 'fj', '679'],
['Finland (Suomi)', 'fi', '358', 0],
['France', 'fr', '33'],
['French Guiana (Guyane française)', 'gf', '594'],
['French Polynesia (Polynésie française)', 'pf', '689'],
['Gabon', 'ga', '241'],
['Gambia', 'gm', '220'],
['Georgia (საქართველო)', 'ge', '995'],
['Germany (Deutschland)', 'de', '49'],
['Ghana (Gaana)', 'gh', '233'],
['Gibraltar', 'gi', '350'],
['Greece (Ελλάδα)', 'gr', '30'],
['Greenland (Kalaallit Nunaat)', 'gl', '299'],
['Grenada', 'gd', '1', 4, ['473']],
['Guadeloupe', 'gp', '590', 0],
['Guam', 'gu', '1', 4, ['671']],
['Guatemala', 'gt', '502'],
['Guernsey', 'gg', '44', 1],
['Guinea (Guinée)', 'gn', '224'],
['Guinea-Bissau (Guiné Bissau)', 'gw', '245'],
['Guyana', 'gy', '592'],
['Haiti', 'ht', '509'],
['Honduras', 'hn', '504'],
['Hong Kong (香港)', 'hk', '852'],
['Hungary (Magyarország)', 'hu', '36'],
['Iceland (Ísland)', 'is', '354'],
['India (भारत)', 'in', '91'],
['Indonesia', 'id', '62'],
['Iran (ایران)', 'ir', '98'],
['Iraq (العراق)', 'iq', '964'],
['Ireland', 'ie', '353'],
['Isle of Man', 'im', '44', 2],
['Israel (ישראל)', 'il', '972'],
['Italy (Italia)', 'it', '39', 0],
['Jamaica', 'jm', '1', 4, ['876', '658']],
['Japan (日本)', 'jp', '81'],
['Jersey', 'je', '44', 3],
['Jordan (الأردن)', 'jo', '962'],
['Kazakhstan (Казахстан)', 'kz', '7', 1],
['Kenya', 'ke', '254'],
['Kiribati', 'ki', '686'],
['Kosovo', 'xk', '383'],
['Kuwait (الكويت)', 'kw', '965'],
['Kyrgyzstan (Кыргызстан)', 'kg', '996'],
['Laos (ລາວ)', 'la', '856'],
['Latvia (Latvija)', 'lv', '371'],
['Lebanon (لبنان)', 'lb', '961'],
['Lesotho', 'ls', '266'],
['Liberia', 'lr', '231'],
['Libya (ليبيا)', 'ly', '218'],
['Liechtenstein', 'li', '423'],
['Lithuania (Lietuva)', 'lt', '370'],
['Luxembourg', 'lu', '352'],
['Macau (澳門)', 'mo', '853'],
['Macedonia (FYROM) (Македонија)', 'mk', '389'],
['Madagascar (Madagasikara)', 'mg', '261'],
['Malawi', 'mw', '265'],
['Malaysia', 'my', '60'],
['Maldives', 'mv', '960'],
['Mali', 'ml', '223'],
['Malta', 'mt', '356'],
['Marshall Islands', 'mh', '692'],
['Martinique', 'mq', '596'],
['Mauritania (موريتانيا)', 'mr', '222'],
['Mauritius (Moris)', 'mu', '230'],
['Mayotte', 'yt', '262', 1],
['Mexico (México)', 'mx', '52'],
['Micronesia', 'fm', '691'],
['Moldova (Republica Moldova)', 'md', '373'],
['Monaco', 'mc', '377'],
['Mongolia (Монгол)', 'mn', '976'],
['Montenegro (Crna Gora)', 'me', '382'],
['Montserrat', 'ms', '1664'],
['Morocco (المغرب)', 'ma', '212', 0],
['Mozambique (Moçambique)', 'mz', '258'],
['Myanmar (Burma) (မြန်မာ)', 'mm', '95'],
['Namibia (Namibië)', 'na', '264'],
['Nauru', 'nr', '674'],
['Nepal (नेपाल)', 'np', '977'],
['Netherlands (Nederland)', 'nl', '31'],
['New Caledonia (Nouvelle-Calédonie)', 'nc', '687'],
['New Zealand', 'nz', '64'],
['Nicaragua', 'ni', '505'],
['Niger (Nijar)', 'ne', '227'],
['Nigeria', 'ng', '234'],
['Niue', 'nu', '683'],
['Norfolk Island', 'nf', '672'],
['North Korea (조선 민주주의 인민 공화국)', 'kp', '850'],
['Northern Mariana Islands', 'mp', '1670'],
['Norway (Norge)', 'no', '47', 0],
['Oman (عُمان)', 'om', '968'],
['Pakistan (پاکستان)', 'pk', '92'],
['Palau', 'pw', '680'],
['Palestine (فلسطين)', 'ps', '970'],
['Panama (Panamá)', 'pa', '507'],
['Papua New Guinea', 'pg', '675'],
['Paraguay', 'py', '595'],
['Peru (Perú)', 'pe', '51'],
['Philippines', 'ph', '63'],
['Poland (Polska)', 'pl', '48'],
['Portugal', 'pt', '351'],
['Puerto Rico', 'pr', '1', 3, ['787', '939']],
['Qatar (قطر)', 'qa', '974'],
['Réunion (La Réunion)', 're', '262', 0],
['Romania (România)', 'ro', '40'],
['Russia (Россия)', 'ru', '7', 0],
['Rwanda', 'rw', '250'],
['Saint Barthélemy', 'bl', '590', 1],
['Saint Helena', 'sh', '290'],
['Saint Kitts and Nevis', 'kn', '1', 4, ['869']],
['Saint Lucia', 'lc', '1', 4, ['758']],
['Saint Martin (Saint-Martin (partie française))', 'mf', '590', 2],
['Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)', 'pm', '508'],
['Saint Vincent and the Grenadines', 'vc', '1784'],
['Samoa', 'ws', '685'],
['San Marino', 'sm', '378'],
['São Tomé and Príncipe (São Tomé e Príncipe)', 'st', '239'],
['Saudi Arabia (المملكة العربية السعودية)', 'sa', '966'],
['Senegal (Sénégal)', 'sn', '221'],
['Serbia (Србија)', 'rs', '381'],
['Seychelles', 'sc', '248'],
['Sierra Leone', 'sl', '232'],
['Singapore', 'sg', '65'],
['Sint Maarten', 'sx', '1', 4, ['721']],
['Slovakia (Slovensko)', 'sk', '421'],
['Slovenia (Slovenija)', 'si', '386'],
['Solomon Islands', 'sb', '677'],
['Somalia (Soomaaliya)', 'so', '252'],
['South Africa', 'za', '27'],
['South Korea (대한민국)', 'kr', '82'],
['South Sudan (جنوب السودان)', 'ss', '211'],
['Spain (España)', 'es', '34'],
['Sri Lanka (ශ්රී ලංකාව)', 'lk', '94'],
['Sudan (السودان)', 'sd', '249'],
['Suriname', 'sr', '597'],
['Svalbard and Jan Mayen', 'sj', '47', 1],
['Swaziland', 'sz', '268'],
['Sweden (Sverige)', 'se', '46'],
['Switzerland (Schweiz)', 'ch', '41'],
['Syria (سوريا)', 'sy', '963'],
['Taiwan (台灣)', 'tw', '886'],
['Tajikistan', 'tj', '992'],
['Tanzania', 'tz', '255'],
['Thailand (ไทย)', 'th', '66'],
['Timor-Leste', 'tl', '670'],
['Togo', 'tg', '228'],
['Tokelau', 'tk', '690'],
['Tonga', 'to', '676'],
['Trinidad and Tobago', 'tt', '1', 4, ['868']],
['Tunisia (تونس)', 'tn', '216'],
['Turkey (Türkiye)', 'tr', '90'],
['Turkmenistan', 'tm', '993'],
['Turks and Caicos Islands', 'tc', '1', 4, ['649']],
['Tuvalu', 'tv', '688'],
['U.S. Virgin Islands', 'vi', '1', 4, ['340']],
['Uganda', 'ug', '256'],
['Ukraine (Україна)', 'ua', '380'],
['United Arab Emirates (الإمارات العربية المتحدة)', 'ae', '971'],
['United Kingdom', 'gb', '44', 0],
['United States', 'us', '1', 0],
['Uruguay', 'uy', '598'],
['Uzbekistan (Oʻzbekiston)', 'uz', '998'],
['Vanuatu', 'vu', '678'],
['Vatican City (Città del Vaticano)', 'va', '39', 1],
['Venezuela', 've', '58'],
['Vietnam (Việt Nam)', 'vn', '84'],
['Wallis and Futuna (Wallis-et-Futuna)', 'wf', '681'],
['Western Sahara (الصحراء الغربية)', 'eh', '212', 1],
['Yemen (اليمن)', 'ye', '967'],
['Zambia', 'zm', '260'],
['Zimbabwe', 'zw', '263'],
['Åland Islands', 'ax', '358', 1],
];
const EXAMPLES = {
// Examples
'001': '001',
AC: '40123',
AD: '312345',
AE: '501234567',
AF: '701234567',
AG: '2684641234',
AI: '2642351234',
AL: '662123456',
AM: '77123456',
AO: '923123456',
AR: '91123456789',
AS: '6847331234',
AT: '664123456',
AU: '412345678',
AW: '5601234',
AX: '412345678',
AZ: '401234567',
BA: '61123456',
BB: '2462501234',
BD: '1812345678',
BE: '470123456',
BF: '70123456',
BG: '48123456',
BH: '36001234',
BI: '79561234',
BJ: '90011234',
BL: '690001234',
BM: '4413701234',
BN: '7123456',
BO: '71234567',
BQ: '3181234',
BR: '11961234567',
BS: '2423591234',
BT: '17123456',
BW: '71123456',
BY: '294911911',
BZ: '6221234',
CA: '5062345678',
CC: '412345678',
CD: '991234567',
CF: '70012345',
CG: '061234567',
CH: '781234567',
CI: '01234567',
CK: '71234',
CL: '221234567',
CM: '671234567',
CN: '13123456789',
CO: '3211234567',
CR: '83123456',
CU: '51234567',
CV: '9911234',
CW: '95181234',
CX: '412345678',
CY: '96123456',
CZ: '601123456',
DE: '15123456789',
DJ: '77831001',
DK: '32123456',
DM: '7672251234',
DO: '8092345678',
DZ: '551234567',
EC: '991234567',
EE: '51234567',
EG: '1001234567',
EH: '650123456',
ER: '7123456',
ES: '612345678',
ET: '911234567',
FI: '412345678',
FJ: '7012345',
FK: '51234',
FM: '3501234',
FO: '211234',
FR: '612345678',
GA: '06031234',
GB: '7400123456',
GD: '4734031234',
GE: '555123456',
GF: '694201234',
GG: '7781123456',
GH: '231234567',
GI: '57123456',
GL: '221234',
GM: '3012345',
GN: '601123456',
GP: '690001234',
GQ: '222123456',
GR: '6912345678',
GT: '51234567',
GU: '6713001234',
GW: '955012345',
GY: '6091234',
HK: '51234567',
HN: '91234567',
HR: '921234567',
HT: '34101234',
HU: '201234567',
ID: '812345678',
IE: '850123456',
IL: '502345678',
IM: '7924123456',
IN: '8123456789',
IO: '3801234',
IQ: '7912345678',
IR: '9123456789',
IS: '6111234',
IT: '3123456789',
JE: '7797712345',
JM: '8762101234',
JO: '790123456',
JP: '9012345678',
KE: '712123456',
KG: '700123456',
KH: '91234567',
KI: '72001234',
KM: '3212345',
KN: '8697652917',
KP: '1921234567',
KR: '1000000000',
KW: '50012345',
KY: '3453231234',
KZ: '7710009998',
LA: '2023123456',
LB: '71123456',
LC: '7582845678',
LI: '660234567',
LK: '712345678',
LR: '770123456',
LS: '50123456',
LT: '61234567',
LU: '628123456',
LV: '21234567',
LY: '912345678',
MA: '650123456',
MC: '612345678',
MD: '62112345',
ME: '67622901',
MF: '690001234',
MG: '321234567',
MH: '2351234',
MK: '72345678',
ML: '65012345',
MM: '92123456',
MN: '88123456',
MO: '66123456',
MP: '6702345678',
MQ: '696201234',
MR: '22123456',
MS: '6644923456',
MT: '96961234',
MU: '52512345',
MV: '7712345',
MW: '991234567',
MX: '12221234567',
MY: '123456789',
MZ: '821234567',
NA: '811234567',
NC: '751234',
NE: '93123456',
NF: '381234',
NG: '8021234567',
NI: '81234567',
NL: '612345678',
NO: '40612345',
NP: '9841234567',
NR: '5551234',
NU: '8884012',
NZ: '211234567',
OM: '92123456',
PA: '61234567',
PE: '912345678',
PF: '87123456',
PG: '70123456',
PH: '9051234567',
PK: '3012345678',
PL: '512345678',
PM: '551234',
PR: '7872345678',
PS: '599123456',
PT: '912345678',
PW: '6201234',
PY: '961456789',
QA: '33123456',
RE: '692123456',
RO: '712034567',
RS: '601234567',
RU: '9123456789',
RW: '720123456',
SA: '512345678',
SB: '7421234',
SC: '2510123',
SD: '911231234',
SE: '701234567',
SG: '81234567',
SH: '51234',
SI: '31234567',
SJ: '41234567',
SK: '912123456',
SL: '25123456',
SM: '66661212',
SN: '701234567',
SO: '71123456',
SR: '7412345',
SS: '977123456',
ST: '9812345',
SV: '70123456',
SX: '7215205678',
SY: '944567890',
SZ: '76123456',
TA: '8999',
TC: '6492311234',
TD: '63012345',
TG: '90112345',
TH: '812345678',
TJ: '917123456',
TK: '7290',
TL: '77212345',
TM: '66123456',
TN: '20123456',
TO: '7715123',
TR: '5012345678',
TT: '8682911234',
TV: '901234',
TW: '912345678',
TZ: '621234567',
UA: '501234567',
UG: '712345678',
US: '2015550123',
UY: '94231234',
UZ: '912345678',
VA: '3123456789',
VC: '7844301234',
VE: '4121234567',
VG: '2843001234',
VI: '3406421234',
VN: '912345678',
VU: '5912345',
WF: '501234',
WS: '7212345',
XK: '43201234',
YE: '712345678',
YT: '639012345',
ZA: '711234567',
ZM: '955123456',
ZW: '712345678',
};
const ngxMatInputTelValidator = (control) => {
const error = { validatePhoneNumber: true };
let numberInstance;
if (control.value) {
try {
numberInstance = parsePhoneNumber(control.value);
}
catch (e) {
return error;
}
if (numberInstance && !numberInstance.isValid()) {
if (!control.touched) {
control.markAsTouched();
}
return error;
}
}
return null;
};
class SearchPipe {
transform(countries, searchCriteria) {
if (!searchCriteria || searchCriteria === '') {
return countries;
}
return countries.filter((country) => {
return `${country.name}+${country.dialCode}${country.areaCodes ? country.areaCodes.join(',') : ''}`
.toLowerCase()
.includes(searchCriteria.toLowerCase());
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: SearchPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.1", ngImport: i0, type: SearchPipe, isStandalone: true, name: "search" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: SearchPipe, decorators: [{
type: Pipe,
args: [{
name: 'search',
standalone: true,
}]
}] });
class ngxMatInputTelBase {
_defaultErrorStateMatcher;
_parentForm;
_parentFormGroup;
ngControl;
constructor(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, ngControl) {
this._defaultErrorStateMatcher = _defaultErrorStateMatcher;
this._parentForm = _parentForm;
this._parentFormGroup = _parentFormGroup;
this.ngControl = ngControl;
}
}
class NgxMatInputTelComponent extends ngxMatInputTelBase {
_changeDetectorRef;
_focusMonitor;
_elementRef;
static nextId = 0;
matMenu;
menuSearchInput;
focusable;
id = `ngx-mat-input-tel-${NgxMatInputTelComponent.nextId++}`;
get shouldLabelFloat() {
return this.focused || !this.empty;
}
autocomplete = 'off';
cssClass;
errorStateMatcher = this._defaultErrorStateMatcher;
placeholder = '';
maxLength = 15;
name;
preferredCountries = [];
_onlyCountries = [];
set onlyCountries(countries) {
this._onlyCountries = countries;
if (this._onlyCountries.length)
this.$availableCountries.set(this._allCountries.filter((c) => this._onlyCountries.includes(c.iso2)));
this._setDefaultCountry();
this._setPreferredCountriesInDropDown();
}
searchPlaceholder = 'Search ...';
validation = 'isValid';
enablePlaceholder = false;
enableSearch = false;
resetOnChange = false;
set format(value) {
this._format = value;
this.phoneNumber = this.formattedPhoneNumber();
this.stateChanges.next();
}
get format() {
return this._format;
}
_required = false;
set required(value) {
this._required = coerceBooleanProperty(value);
this.stateChanges.next(undefined);
}
get required() {
return this._required;
}
_disabled = false;
set disabled(value) {
this._disabled = coerceBooleanProperty(value);
this.stateChanges.next(undefined);
}
get disabled() {
return this._disabled;
}
get empty() {
return !this.phoneNumber;
}
countryChanged = new EventEmitter();
stateChanges = new Subject();
focused = false;
describedBy = '';
phoneNumber = '';
_allCountries = [];
$availableCountries = signal(this._initAllCountries());
$preferredCountriesInDropDown = signal([]);
$selectedCountry;
numberInstance;
value;
searchCriteria;
_previousFormattedNumber;
_format = 'default';
onTouched = () => { };
propagateChange = (_) => { };
errorState;
constructor(_changeDetectorRef, _focusMonitor, _elementRef, _ngControl, _parentForm, _parentFormGroup, _defaultErrorStateMatcher) {
super(_defaultErrorStateMatcher, _parentForm, _parentFormGroup, _ngControl);
this._changeDetectorRef = _changeDetectorRef;
this._focusMonitor = _focusMonitor;
this._elementRef = _elementRef;
_focusMonitor.monitor(_elementRef, true).subscribe((origin) => {
if (this.focused && !origin) {
this.onTouched();
}
this.focused = !!origin;
this.stateChanges.next();
});
if (this.ngControl != null) {
this.ngControl.valueAccessor = this;
}
}
ngOnInit() {
this._setDefaultCountry();
this._setPreferredCountriesInDropDown();
this._changeDetectorRef.markForCheck();
this.stateChanges.next();
}
_setPreferredCountriesInDropDown(availableCountries = this.$availableCountries(), countries = this.preferredCountries) {
this.$preferredCountriesInDropDown.set(availableCountries.filter((c) => countries.includes(c.iso2)) || []);
}
updateErrorState() {
if (this.ngControl &&
this.ngControl.invalid &&
(this.ngControl.touched || (this._parentForm && this._parentForm.submitted))) {
const currentState = this.errorStateMatcher.isErrorState(this.ngControl.control, this.ngControl?.value);
if (currentState !== this.errorState) {
this.errorState = currentState;
this._changeDetectorRef.markForCheck();
}
}
}
_setDefaultCountry() {
let country;
if (this.numberInstance?.country) {
// If an existing number is present, we use it to determine country
country = this.getCountry(this.numberInstance.country);
}
else if (this.$preferredCountriesInDropDown().length) {
country = this.$preferredCountriesInDropDown()[0];
}
else {
country = this._allCountries[0];
}
this.$selectedCountry = signal(country);
this.countryChanged.emit(country);
}
ngDoCheck() {
if (this.ngControl) {
const oldState = this.errorState;
const newState = this.errorStateMatcher.isErrorState(this.ngControl.control, this._parentForm);
this.errorState =
(newState && (!this.ngControl.control?.value || this.ngControl.control?.touched)) ||
(!this.focused ? newState : false);
if (oldState !== newState) {
this.errorState = newState;
this.stateChanges.next();
}
}
}
ngOnDestroy() {
this.stateChanges.complete();
this._focusMonitor.stopMonitoring(this._elementRef);
}
onPhoneNumberChange() {
try {
this._setCountry();
}
catch (e) {
// Pass a value to trigger the validator error
this.value = this.formattedPhoneNumber().toString();
}
this.propagateChange(this.value);
this._changeDetectorRef.markForCheck();
}
_setCountry() {
if (!this.phoneNumber) {
this.value = null;
return;
}
const numberInstance = parsePhoneNumberFromString(this.phoneNumber.toString(), this.$selectedCountry().iso2.toUpperCase());
if (!numberInstance)
return;
this.numberInstance = numberInstance;
this.formatAsYouTypeIfEnabled();
this.value = this.numberInstance?.number;
if (!this.value)
throw new Error('Incorrect phone number');
if (this.numberInstance &&
(this.validation === 'isPossible'
? this.numberInstance.isPossible()
: this.numberInstance.isValid())) {
if (this.phoneNumber !== this.formattedPhoneNumber()) {
this.phoneNumber = this.formattedPhoneNumber();
}
if (this.$selectedCountry().iso2 !== this.numberInstance.country &&
this.numberInstance.country) {
this.$selectedCountry.set(this.getCountry(this.numberInstance.country));
this.countryChanged.emit(this.$selectedCountry());
}
}
}
onCountrySelect(country, el) {
if (this.phoneNumber) {
this.phoneNumber = this.numberInstance?.nationalNumber;
}
if (this.resetOnChange && this.$selectedCountry() !== country) {
this.reset();
}
this.$selectedCountry.set(country);
this.countryChanged.emit(this.$selectedCountry());
this.onPhoneNumberChange();
el.focus();
}
getCountry(code) {
return (this._allCountries.find((c) => c.iso2 === code.toLowerCase()) || {
name: 'UN',
iso2: 'UN',
dialCode: undefined,
priority: 0,
areaCodes: undefined,
flagClass: 'UN',
placeHolder: '',
});
}
onInputKeyPress(event) {
const pattern = /[0-9+\- ]/;
if (!pattern.test(event.key)) {
event.preventDefault();
}
}
_initAllCountries() {
this._allCountries = ALL_COUNTRIES.map((c) => {
const country = {
name: c[0].toString(),
iso2: c[1].toString(),
dialCode: c[2].toString(),
priority: +c[3] || 0,
areaCodes: c[4] || undefined,
flagClass: c[1].toString().toUpperCase(),
placeHolder: '',
};
if (this.enablePlaceholder) {
country.placeHolder = this._getPhoneNumberPlaceHolder(country.iso2.toUpperCase());
}
return country;
});
return this._allCountries;
}
_getPhoneNumberPlaceHolder(countryISOCode) {
try {
return getExampleNumber(countryISOCode, EXAMPLES)?.number;
}
catch (e) {
return e;
}
}
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
this._changeDetectorRef.markForCheck();
this.stateChanges.next(undefined);
}
writeValue(value) {
if (value) {
this.numberInstance = parsePhoneNumberFromString(value);
if (this.numberInstance) {
const countryCode = this.numberInstance.country;
this.phoneNumber = this.formattedPhoneNumber();
if (!countryCode)
return;
if (!this.$selectedCountry) {
// Init value was given
this.$selectedCountry = signal(this.getCountry(countryCode));
}
else {
this.$selectedCountry.set(this.getCountry(countryCode));
}
if (this.$selectedCountry().dialCode &&
!this.preferredCountries.includes(this.$selectedCountry().iso2)) {
this.$preferredCountriesInDropDown.update((values) => {
return [...values, this.$selectedCountry()];
});
}
this.countryChanged.emit(this.$selectedCountry());
// Initial value is set
this.stateChanges.next();
}
else {
this.phoneNumber = value;
this.stateChanges.next(undefined);
}
}
// Value is set from outside using setValue()
this.onPhoneNumberChange();
this._changeDetectorRef.markForCheck();
}
setDescribedByIds(ids) {
this.describedBy = ids.join(' ');
}
onContainerClick(event) {
if (event.target.tagName.toLowerCase() !== 'input') {
this._elementRef.nativeElement.querySelector('input').focus();
}
}
reset() {
this.phoneNumber = '';
this.propagateChange(null);
this._changeDetectorRef.markForCheck();
this.stateChanges.next(undefined);
}
formattedPhoneNumber() {
if (!this.numberInstance) {
return (this.phoneNumber?.toString() || '');
}
switch (this.format) {
case 'national':
return this.numberInstance.formatNational();
case 'international':
return this.numberInstance.formatInternational();
default:
return this.numberInstance.nationalNumber.toString();
}
}
formatAsYouTypeIfEnabled() {
if (this.format === 'default') {
return;
}
const asYouType = new AsYouType(this.$selectedCountry().iso2.toUpperCase());
// To avoid caret positioning we apply formatting only if the caret is at the end:
if (!this.phoneNumber)
return;
if (this.phoneNumber?.toString().startsWith(this._previousFormattedNumber || '')) {
this.phoneNumber = asYouType.input(this.phoneNumber.toString());
}
this._previousFormattedNumber = this.phoneNumber.toString();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: NgxMatInputTelComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.FocusMonitor }, { token: i0.ElementRef }, { token: i2.NgControl, optional: true, self: true }, { token: i2.NgForm, optional: true }, { token: i2.FormGroupDirective, optional: true }, { token: i3.ErrorStateMatcher }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: NgxMatInputTelComponent, isStandalone: true, selector: "ngx-mat-input-tel", inputs: { autocomplete: "autocomplete", cssClass: "cssClass", errorStateMatcher: "errorStateMatcher", placeholder: "placeholder", maxLength: "maxLength", name: "name", preferredCountries: "preferredCountries", onlyCountries: "onlyCountries", searchPlaceholder: "searchPlaceholder", validation: "validation", enablePlaceholder: ["enablePlaceholder", "enablePlaceholder", booleanAttribute], enableSearch: ["enableSearch", "enableSearch", booleanAttribute], resetOnChange: ["resetOnChange", "resetOnChange", booleanAttribute], format: "format", required: ["required", "required", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute] }, outputs: { countryChanged: "countryChanged" }, host: { properties: { "id": "this.id", "class.ngx-floating": "this.shouldLabelFloat" } }, providers: [
{ provide: MatFormFieldControl, useExisting: NgxMatInputTelComponent },
{
provide: NG_VALIDATORS,
useValue: ngxMatInputTelValidator,
multi: true,
},
], viewQueries: [{ propertyName: "matMenu", first: true, predicate: MatMenu, descendants: true }, { propertyName: "menuSearchInput", first: true, predicate: ["menuSearchInput"], descendants: true }, { propertyName: "focusable", first: true, predicate: ["focusable"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ngx-mat-input-tel-container\">\n <button\n type=\"button\"\n matRipple\n [matMenuTriggerFor]=\"menu\"\n class=\"country-selector\"\n [disabled]=\"disabled\"\n (menuOpened)=\"menuSearchInput?.nativeElement?.focus()\"\n >\n <span class=\"country-selector-flag flag\" [ngClass]=\"$selectedCountry().flagClass\"></span>\n\n @if ($selectedCountry().dialCode) {\n <span class=\"country-selector-code\">+{{ $selectedCountry().dialCode }}</span>\n }\n </button>\n\n <mat-menu\n #menu=\"matMenu\"\n class=\"ngx-mat-input-tel-overlay-pane\"\n [backdropClass]=\"'ngx-mat-input-tel-overlay-backdrop'\"\n >\n @if (enableSearch) {\n <input\n #menuSearchInput\n class=\"country-search\"\n [(ngModel)]=\"searchCriteria\"\n type=\"text\"\n [placeholder]=\"searchPlaceholder\"\n (click)=\"$event.stopPropagation()\"\n style=\"\n width: calc(100% - 4px);\n height: 34px;\n border-top: none;\n border-right: none;\n border-left: none;\n border-image: initial;\n border-bottom: 1px solid rgb(221, 221, 221);\n font-size: 14px;\n padding: 20px 10px 24px;\n box-sizing: border-box;\n background: transparent;\n margin: 2px;\n \"\n />\n }\n @for (country of $preferredCountriesInDropDown(); track $index) {\n <button\n type=\"button\"\n mat-menu-item\n class=\"country-list-button\"\n (click)=\"onCountrySelect(country, focusable)\"\n >\n <div class=\"icon-wrapper\">\n <div class=\"flag\" [ngClass]=\"country.flagClass\"></div>\n </div>\n <div class=\"label-wrapper\">\n {{ country.name }}\n\n @if (country?.dialCode) {\n <span [style]=\"!searchCriteria ? 'white-space: nowrap' : ''\"\n >+{{ country.dialCode }}\n\n @if (country.areaCodes) {\n {{ country.areaCodes.join(', ') }}\n }\n </span>\n }\n </div>\n </button>\n }\n @if ($preferredCountriesInDropDown().length) {\n <mat-divider></mat-divider>\n }\n @for (country of $availableCountries() | search: searchCriteria; track $index) {\n <button\n type=\"button\"\n mat-menu-item\n class=\"country-list-button\"\n (click)=\"onCountrySelect(country, focusable)\"\n >\n <div class=\"icon-wrapper\">\n <div class=\"flag\" [ngClass]=\"country.flagClass\"></div>\n </div>\n <div class=\"label-wrapper\">\n {{ country.name }}\n\n @if (country?.dialCode) {\n <span [style]=\"!searchCriteria ? 'white-space: nowrap' : ''\"\n >+{{ country.dialCode }}\n\n @if (country.areaCodes) {\n {{ country.areaCodes.join(', ') }}\n }\n </span>\n }\n </div>\n </button>\n }\n </mat-menu>\n\n <input\n class=\"ngx-mat-input-tel-input\"\n matInput\n type=\"tel\"\n inputmode=\"tel\"\n [autocomplete]=\"autocomplete\"\n [ngClass]=\"cssClass\"\n (blur)=\"onTouched()\"\n (keypress)=\"onInputKeyPress($event)\"\n [(ngModel)]=\"phoneNumber\"\n (ngModelChange)=\"onPhoneNumberChange()\"\n [errorStateMatcher]=\"errorStateMatcher\"\n [placeholder]=\"placeholder || $selectedCountry().placeHolder || ''\"\n [disabled]=\"disabled\"\n #focusable\n [maxlength]=\"maxLength\"\n />\n</div>\n", styles: ["@media print{:host{--ngxMatInputTel-flag-display: none}}:host.ngx-floating .country-selector,:host.ngx-floating input.ngx-mat-input-tel-input::placeholder{opacity:1}:host .ngx-mat-input-tel-container{display:flex;height:var(--ngxMatInputTel-height, 24px)}:host input{border:none;background:none;outline:none;font:inherit;width:100%;box-sizing:border-box;padding-right:6px;padding-left:4px;position:relative;z-index:0}:host input.ngx-mat-input-tel-input::placeholder{opacity:var(--ngxMatInputTel-placeholder-opacity, var(--ngxMatInputTel-opacity, 0))}:host .icon-wrapper{padding-right:24px}:host .flag{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAABw4CAMAAAAs8X1iAAADAFBMVEUAAAD////OESYAJH0AAAAAK3/80RbtKTn/ywDRETPQFCvYJx7/AAAAejkAI5UANpV0rt0AZTTvKy3BAQPCJy1Bid3eKg8AnUkAlETgGx3VAQD93QXtHCQAeF8AN6YBhU0AakLeChcAAIzKLzwAKWb91AActTr94wAAo17209YAbcsCrsnHDR/kABLoES0AcsEiRY1LktoAak4DJ4s6ecn38/ABHqERSK8DaacBod3GDDDYFDsAgAASrSsDlsAHiTBpuuYCKKYAmzpKrdYAP4j9zyT1s7YAZgAAV6VmzP8ormbeFh4EUZkkSaX630X0rgG6CC6eLzoPPHytHSX33xYZigABPppKl88BPxw6gj3WZHTe5/DZECNbl7H6uBEAlWcBS6joKDoAAGYaRJHlAjb1xsrZJBEAXbsCf/3gUmEjnkLNDCwANrKdqsrVJyftHSjjPDIvmzAMBwTnbnKMGj3mqK/B0eT8OjKyIjQhXDNAWInzlpX950kNXq8ei0M+bU3////c29r/cgDsho3idQnsAAD9TRQ+XrivDgv2gwFLqFZeteMWFpbgACXuxQmakKswVpmnp6X+xh3PSFB/rY8AUbrgTwf+mjIjXEI7eCgAmQDasjM/mQEiG1ASiAeozbbGvcOLJyqNqdbPf4ejyuxRfMB/msPelZ0NrS00sjBtg7hLaaPxK0IZIG0/PnEwkAngUCWwigqxxNpTSgfCHhp/teHG0rzk7uYOdCjy3roAUPBNL2rSuhy1uAglMXTHujMxLRHFpV59CRBvjTp4YmiUsjy1oyHqkBdguI3CdyFtaZFHlHNUWlWLgyqOh4ZyhnMpd2XseCNnXDOmUzh7awhLiKQzDw2yNFDvQ02RqGZagyxpoKt6tB5PaIWRxZrFQBxDTEB5flJsOE9SCxp6MBimuIf24p3sf0nltl5Ds5PYw4DPrJzAfVf22XudPyMSOTn///8CNwPAGTilUGUCi0b////MECjvKiwAMoze8+gABhCSwecEfcgAOJTnESwetTri0eK2AAABAHRSTlMA/////////////////////////////////////////////////////////////////v////3///7///////////7//f/////+///////////+//////7//////////f/////////////9/vz//////////v3//f///////////vz///7////////////////+//7/////////////////+////v/9/v7///////////7//v///v////7//////f///////v///////v////7//////v/+///+//v//////////v/////+//3//v/////U/9f7pY6kfJrKwsC2SaOqKyxZfwAAjiFJREFUeJzsvQ1cVNe97z0bBgRiG6MkPY3JPecTYsy0NiGtu/Ym57WN0z5pDBGbkyvTcNpL6DnkdIgZyphAm2QufKIxdhyETxIfkjIRHW+GlPLmTPhkVEDlRWEIiESivImgAtLTa3uf89zzfO591tovM/tlrb3XShyc0P1Thz17/7/r//uvtfaW2TOzt8kUcxXkM/bMRChLWpqFW8jck1OQn4iRCW7kEQHI5NdggcQ8EeEAITwPFw+ARBGBADo8SQpYIipOSyuOPotG14Xn9niiQBpGkYjMudkrs35yIOn06a1bR0owlqwIS+dvA+qXFZ1pZ/ILcvbAovmlTGnBdadPv316NCkKCOF5fLfmKZCk2pz5+fnrBbURQAyPDJyAiEBOz/x8T09PjpjCJIZLpgaHRIAz85U9GZW1ESBRW0kuS9AC/rpIgUT/5Etnz740GRkI3QxNI/uczn0jTYRAUu11T93x43We62IR2kB9uL3dxe77lHW1t4frCYCS+dnZPb66Ot+e2dn5EhJL4enp2VnuX0WYqAagURA/PRp5qg8oFI/AUtAX9NgqA3SPrUpA99iamHjvvZTA229jLamOrUl1nqTstyeOJkWyaB9bk0r8Z79ZMnqqxPf2X5UkCYD2sTXz42zPKPhXEjmQ6RxbR0vqTo2+fVtJnfg/hM6x9eipUX/JaP3vR0f7j0ZrwOvomVMlTU32Jqf91IkzRwmAE/MnRnfUeTx1nlMnLl/UB949c+ZEid3+d39n31PfP7/5t7rAxfcmj2b/4O8ef/xL/5h9dHL+I13goxOj9W9/s9vpOv3NV97uPXNRFzh66tSpV9721NVt+viU/9RovS6QXT9aUn80Me/WxLrRU/X12boASksCWApaLtGXCGQAsQcYfb1qANTAqwSSAWYCGUBsgEWRPOcqmf5vmQzg8wHrWuiAlkqgjBZiID0DEC3p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