@@ -191,7 +191,7 @@ export class SiPhoneNumberInputComponent
191191 readonly errormessageId = input ( `${ this . id ( ) } -errormessage` ) ;
192192
193193 protected readonly phoneInput = viewChild . required < ElementRef < HTMLInputElement > > ( 'phoneInput' ) ;
194- protected selectedCountry ?: CountryInfo ;
194+ protected readonly selectedCountry = signal < CountryInfo | undefined > ( undefined ) ;
195195 protected placeholder = '' ;
196196 protected readonly countryFocused = signal ( false ) ;
197197 protected open = false ;
@@ -221,7 +221,14 @@ export class SiPhoneNumberInputComponent
221221 ) ;
222222 private readonly disabledNgControl = signal ( false ) ;
223223 private isValidNumber = true ;
224- private phoneNumber ?: PhoneNumber ;
224+ private readonly phoneNumber = signal < PhoneNumber | undefined > ( undefined , {
225+ equal : ( a , b ) => {
226+ if ( ! a || ! b ) {
227+ return ! a && ! b ;
228+ }
229+ return this . phoneUtil . isNumberMatch ( a , b ) === PhoneNumberUtil . MatchType . EXACT_MATCH ;
230+ }
231+ } ) ;
225232 private onChange : ( val : string ) => void = ( ) => { } ;
226233 private onTouched : ( ) => void = ( ) => { } ;
227234
@@ -233,8 +240,9 @@ export class SiPhoneNumberInputComponent
233240
234241 /** @internal */
235242 writeValue ( value : string | undefined ) : void {
236- this . phoneNumber = this . parseNumber ( value ) ;
237- if ( this . phoneNumber ) {
243+ const phoneNumber = this . parseNumber ( value ) ;
244+ this . phoneNumber . set ( phoneNumber ) ;
245+ if ( phoneNumber ) {
238246 this . writeValueToInput ( ) ;
239247 this . country . set ( this . getRegionCode ( ) ) ;
240248 } else {
@@ -268,13 +276,14 @@ export class SiPhoneNumberInputComponent
268276 }
269277
270278 this . isValidNumber = false ;
271- if ( ! this . phoneNumber || ! this . phoneUtil . isValidNumber ( this . phoneNumber ) ) {
279+ const phoneNumber = this . phoneNumber ( ) ;
280+ if ( ! phoneNumber || ! this . phoneUtil . isValidNumber ( phoneNumber ) ) {
272281 return {
273282 invalidPhoneNumberFormat : true
274283 } ;
275284 }
276285
277- if ( ! this . countryList ( ) . some ( c => c . value . isoCode === this . selectedCountry ! . isoCode ) ) {
286+ if ( ! this . countryList ( ) . some ( c => c . value . isoCode === this . selectedCountry ( ) ! . isoCode ) ) {
278287 return {
279288 notSupportedPhoneNumberCountry : true
280289 } ;
@@ -286,25 +295,26 @@ export class SiPhoneNumberInputComponent
286295
287296 protected input ( ) : void {
288297 const rawNumber = this . phoneInput ( ) . nativeElement . value ;
289- this . phoneNumber = this . parseNumber ( rawNumber ) ;
298+ const phoneNumber = this . parseNumber ( rawNumber ) ;
299+ this . phoneNumber . set ( phoneNumber ) ;
290300
291- if ( this . phoneNumber ) {
301+ if ( phoneNumber ) {
292302 const regionCode = this . getRegionCode ( ) ;
293303 let countryInfo = this . countryList ( ) . find (
294304 country => regionCode === country . value . isoCode
295305 ) ?. value ;
296306 if ( ! countryInfo && regionCode ) {
297307 countryInfo = {
298308 name : this . getCountryName ( regionCode ) ,
299- countryCode : this . phoneNumber . getCountryCode ( ) ! ,
309+ countryCode : phoneNumber . getCountryCode ( ) ! ,
300310 isoCode : regionCode
301311 } ;
302312 }
303- if ( countryInfo && this . selectedCountry ?. isoCode !== countryInfo . isoCode ) {
304- this . selectedCountry = countryInfo ;
313+ if ( countryInfo && this . selectedCountry ( ) ?. isoCode !== countryInfo . isoCode ) {
314+ this . selectedCountry . set ( countryInfo ) ;
305315 }
306316 } else if ( rawNumber . trim ( ) . startsWith ( '+' ) ) {
307- this . selectedCountry = undefined ;
317+ this . selectedCountry . set ( undefined ) ;
308318 }
309319
310320 this . handleChange ( ) ;
@@ -315,14 +325,14 @@ export class SiPhoneNumberInputComponent
315325 this . onTouched ( ) ;
316326 this . writeValueToInput ( ) ;
317327 this . valueChange . emit ( {
318- country : this . selectedCountry ,
328+ country : this . selectedCountry ( ) ,
319329 phoneNumber : this . formatPhoneNumber ( PhoneNumberFormat . INTERNATIONAL ) ,
320330 isValid : this . isValidNumber
321331 } ) ;
322332 }
323333
324334 protected countryInput ( num : CountryInfo ) : void {
325- this . selectedCountry = num ;
335+ this . selectedCountry . set ( num ) ;
326336 this . updatePlaceholder ( ) ;
327337 this . refreshValueAfterCountryChange ( ) ;
328338 this . handleChange ( ) ;
@@ -342,19 +352,19 @@ export class SiPhoneNumberInputComponent
342352
343353 private writeCountry ( ) : void {
344354 const currentCountry = this . country ( ) ! ;
345- this . selectedCountry = this . countryList ( ) . find (
346- country => country . value . isoCode === currentCountry
347- ) ?. value ;
348- if ( ! this . selectedCountry ) {
355+ this . selectedCountry . set (
356+ this . countryList ( ) . find ( country => country . value . isoCode === currentCountry ) ?. value
357+ ) ;
358+ if ( ! this . selectedCountry ( ) ) {
349359 const countryCode = this . phoneUtil . getCountryCodeForRegion (
350360 currentCountry ?? this . defaultCountry ( ) ?? 'XX'
351361 ) ;
352362 if ( countryCode ) {
353- this . selectedCountry = {
363+ this . selectedCountry . set ( {
354364 isoCode : currentCountry ,
355365 countryCode,
356366 name : this . getCountryName ( currentCountry )
357- } ;
367+ } ) ;
358368 }
359369 }
360370 this . updatePlaceholder ( ) ;
@@ -371,10 +381,11 @@ export class SiPhoneNumberInputComponent
371381 }
372382
373383 private updatePlaceholder ( ) : void {
374- if ( this . selectedCountry ) {
384+ const selectedCountry = this . selectedCountry ( ) ;
385+ if ( selectedCountry ) {
375386 this . placeholder = this . phoneUtil
376387 . format (
377- this . phoneUtil . getExampleNumber ( this . selectedCountry . isoCode ) ,
388+ this . phoneUtil . getExampleNumber ( selectedCountry . isoCode ) ,
378389 PhoneNumberFormat . NATIONAL
379390 )
380391 . replace ( / ^ 0 / , '' ) ;
@@ -385,7 +396,7 @@ export class SiPhoneNumberInputComponent
385396 try {
386397 let regionCodeForParsing : string | undefined ;
387398 if ( ! rawNumber ?. trim ( ) . startsWith ( '+' ) ) {
388- regionCodeForParsing = this . selectedCountry ?. isoCode ;
399+ regionCodeForParsing = this . selectedCountry ( ) ?. isoCode ;
389400 }
390401 return this . phoneUtil . parse ( rawNumber , regionCodeForParsing ) ;
391402 } catch ( e ) {
@@ -399,49 +410,52 @@ export class SiPhoneNumberInputComponent
399410 * This Method fakes a complete number to force PhoneUtil returning a proper region code.
400411 */
401412 private getRegionCode ( ) : string | undefined {
402- if ( this . phoneNumber ) {
403- const regionCode = this . phoneUtil . getRegionCodeForNumber ( this . phoneNumber ) ;
413+ const phoneNumber = this . phoneNumber ( ) ;
414+ if ( phoneNumber ) {
415+ const regionCode = this . phoneUtil . getRegionCodeForNumber ( phoneNumber ) ;
404416 if ( regionCode ) {
405417 return regionCode ;
406418 }
407419
408- const nationalNumber = this . phoneNumber . getNationalNumber ( ) + '' ;
420+ const nationalNumber = phoneNumber . getNationalNumber ( ) + '' ;
409421 if (
410422 // USA, CANADA, ...
411- ( this . phoneNumber . getCountryCode ( ) === 1 && nationalNumber . length >= 3 ) ||
423+ ( phoneNumber . getCountryCode ( ) === 1 && nationalNumber . length >= 3 ) ||
412424 // UK, ...
413- ( this . phoneNumber . getCountryCode ( ) === 44 && nationalNumber . length >= 4 )
425+ ( phoneNumber . getCountryCode ( ) === 44 && nationalNumber . length >= 4 )
414426 ) {
415427 return this . phoneUtil . getRegionCodeForNumber (
416428 this . phoneUtil . parse (
417429 '+' +
418- this . phoneNumber . getCountryCode ( ) +
430+ phoneNumber . getCountryCode ( ) +
419431 nationalNumber +
420432 new Array ( 10 - nationalNumber . length ) . fill ( 5 ) . join ( '' )
421433 )
422434 ) ;
423435 }
424436
425- return this . phoneUtil . getRegionCodeForCountryCode ( this . phoneNumber . getCountryCode ( ) ! ) ;
437+ return this . phoneUtil . getRegionCodeForCountryCode ( phoneNumber . getCountryCode ( ) ! ) ;
426438 }
427439
428440 return undefined ;
429441 }
430442
431443 private formatPhoneNumber ( format : PhoneNumberFormat ) : string | undefined {
432- if ( this . phoneNumber ) {
433- return this . phoneUtil . format ( this . phoneNumber , format ) ;
444+ const phoneNumber = this . phoneNumber ( ) ;
445+ if ( phoneNumber ) {
446+ return this . phoneUtil . format ( phoneNumber , format ) ;
434447 }
435448
436449 return undefined ;
437450 }
438451
439452 private handleChange ( ) : void {
440- if ( this . selectedCountry && this . country ( ) !== this . selectedCountry ?. isoCode ) {
441- this . country . set ( this . selectedCountry ?. isoCode ) ;
453+ const selectedCountry = this . selectedCountry ( ) ;
454+ if ( selectedCountry && this . country ( ) !== selectedCountry . isoCode ) {
455+ this . country . set ( selectedCountry . isoCode ) ;
442456 }
443457
444- if ( this . phoneNumber ) {
458+ if ( this . phoneNumber ( ) ) {
445459 this . onChange ( this . formatPhoneNumber ( PhoneNumberFormat . INTERNATIONAL ) ! ) ;
446460 } else {
447461 this . onChange ( '' ) ;
@@ -455,14 +469,23 @@ export class SiPhoneNumberInputComponent
455469 * Format and update input text or clear input text if the input value is undefined.
456470 */
457471 private writeValueToInput ( ) : void {
458- if ( this . phoneNumber ) {
472+ if ( this . phoneNumber ( ) ) {
459473 this . writeTextToInput ( this . formatPhoneNumber ( PhoneNumberFormat . NATIONAL ) ! . replace ( / ^ 0 / , '' ) ) ;
460474 }
461475 }
462476
463477 private refreshValueAfterCountryChange ( ) : void {
464- if ( this . selectedCountry ) {
465- this . phoneNumber ?. setCountryCode ( this . selectedCountry ?. countryCode ) ;
478+ const selectedCountry = this . selectedCountry ( ) ;
479+ if ( selectedCountry ) {
480+ this . phoneNumber . update ( current => {
481+ if ( ! current ) {
482+ return undefined ;
483+ }
484+ // TODO: Remove any once https://github.com/DefinitelyTyped/DefinitelyTyped/pull/75189 is merged/released
485+ const phoneNumber = ( current as any ) ?. clone ( ) ;
486+ phoneNumber . setCountryCode ( selectedCountry . countryCode ) ;
487+ return phoneNumber ;
488+ } ) ;
466489 this . writeValueToInput ( ) ;
467490 }
468491 }
0 commit comments