UNPKG

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
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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