Angular 7 電話輸入框顯示國家區碼套件 -- 採用 intl-tel-input 套件

原由:

由於工作上需要在網頁上面弄一個框框給使用者輸入手機號碼,我們假設以後會有各個國家的使用者因此需要在手機欄位前面有一個可以選擇國家區碼的『下拉選單』。這種東西網路一定會有『好心』工程師寫好的open source可以用,於是查一下在NPM上面似乎以『intl-tel-input』這個套件最多人用,Github上面的星星數也有37xx個,並還會在下拉選單上面畫出各國的國旗看起來就是賞心悅目。

其實我也有先去搜尋過Angular 的相關套件,但是裝起來都有些問題要不就是已經好久沒在更新了(畢竟我目前用的是Angular 7),所以只好用原生的Javascript 套件整到 Angular 裡面去。

開發環境:


Ubuntu:          18.04 LTS
Angular-Cli 7.0.7
Node:               8.11.4
intl-tel-input:  14.0.6


整合方式:

建立Angular 專案部份我就不介紹了基礎部份這邊就會跳過。
首先在專案下面用 npm 或是 yarn 安裝 intl-tel-input :

# yarn add intl-tel-input

然後接著安裝 typescript 對 intl-tel-input 的定義檔,這個部份安裝時記得加入參數安裝在開發套件的用的。

# yarn add @types/intl-tel-input  --dev


這樣@types/intl-tel-input就會在package.json 內被列在 "devDependencies"這個開發套件區塊。




套用intl-Tel-Input CSS:

接著要套用intl-tel-input的css進來,所以請到 Angular專案下的 src/stuyles.css 內加入 intl-tel-input的css 路徑。由於我們用npm安裝在local所以正常來說會在Angular專案下的/node_modules下,這邊路徑依你的開發環境不同再去微調喔!

styles.css:

@import '../node_modules/intl-tel-input/build/css/intlTelInput.css';


修改typescript compiler的選項

由於我們會直接import  javascript file 以要在Angular 專案下的 tsconfig.json 內加入 "allowJs" : true 避免 vscode 這個開發用的ide會跳出 warning。

tsconfig.json:


Import 到Component:

接著我們將 intl-Tel-Input import 到我們要用他的component的 ts檔內。例如:我有個要讓使用者填寫手機的聯絡我們(contact-us component),所以在程式區import 位於 專案 node_mdoules 下的 intl-Tel-Input javascript 檔:

contact-us.component.ts
import * as intlTelInput from '../../../../node_modules/intl-tel-input/build/js/intlTelInput.js';

然後我們建立一個 public 的 iti 變數在OnInit()內做初始化 intlTelInput 物件
public iti: any;

與 html input 關聯:

這時候我們的 HTML 要給使用者輸入電話號碼的 input 如下:
<input type="text" name="phoneNum" id="phoneNum" formControlName="phoneNum" class="form-control phoneNum" placeholder="手機號碼">

然後在ts 的OnInit() 區內先把這個 input 物件抓出來,這邊看你是要用 Angular 的ElementRef的方式還是 Javascript 原生的 document.querySelector()都可以!我自己是用 Angular的所以程式碼大概如下:

contact-us.component.ts
ngOnInit() { this.phoneInput$ = this.el.nativeElement.querySelector('#phoneNum'); this.iti = intlTelInput( this.phoneInput$, { allowDropdown: true, initialCountry: 'tw', separateDialCode: true } );

這邊說明一下~那個 this.phoneInput$ 是一個我宣告 public 的 HTMLInputElement 型態的變數,用來指定在HTML input 的物件,這邊我抓 id 名稱比較快。

然後原本的iti 就可以拿 phoneInput$ 與 intlTelInput 做關聯。語法大概如下:

intlTelInput( input物件initial 條件 )

後面的初始化條件我這邊就是讓國碼的下拉選單可以下拉( alldowDropdown: true),然後預設國家是台灣( initialCountry: 'tw') 接著讓國碼與國旗一同分開顯示( separateDialCode: true )。這邊還有很多條件可以下,有興趣跟需求的朋友可以到 intl-Tel-Input 的 github 這邊看有哪些條件。這樣在網頁上面的input就會有國碼與國旗的樣式了,其他如果需要調整外觀的就是在css 自行針對 intl-Tel-input 的class 名稱做覆蓋 style code就好了。(記得要在styles.css這裡做覆蓋喔!)

樣子長這樣。

點擊下拉選單後的樣子


拿取使用者的電話:

當使用者輸入電話號碼完之後要如何連同國碼一起拿到呢?就是使用 getNumber()這個內建於 intl-Tel-input 物件的方法

由於我們已經用 iti 指定 iniTelInput了,所以可以在使用者 submit()的程式內,用 this.iti.getNumber() 來獲取。結果如下(我將電話號碼顯示在 瀏覽器的 console 下):


這邊值得注意的事就算你只打 09xxxxxx 或是 9xxxxxxxx 在你按送出的時候,套件會自動幫你在欄位去掉電話開頭的 "0" 然後補上國碼,這樣你用一般的form 表單也不會有什麼問題,但是如果你是用Reactive form的話記得在submit()內用 patchValue 去換掉 form裡的電話號碼喔!



2019-08-23更新:

要使用intl-tel-input 的 static method 之前,必須先建立一個intlTelInput的物件。否則Angular Cli
似乎會因為程式內沒有任何地方需要用 intlTelInput 而不會將這個 Library 載入。

2018-12-27 更新:

如果會用到 intl-tel-input 的 static method
如: window.intlTelInputGlobals.getCountryData()....等 這些在intl-tel-input 擴充在window這個global物件下的方法,會因為typescript 對於 window的方法定義不同造成在編譯時出現 error TS2339: Property 'intlTelInputGlobals' does not exist on type 'Window'. 的錯誤訊息。

舉個例子:
下方程式碼只是單純透過這個 method 列出 intl-tel-input 的所有國家的資訊Array。但是 angular 在typescript 編譯時會出現錯誤。

onSubmit() { console.log( window.intlTelInputGlobals.getCountryData()); }


解決的方式在觀念上就是把 window 轉成 any 型態來避掉 compiler的錯誤,作法大概有兩種

1. 第一種直接在使用window的地方直接用上做轉換。
console.log( (<any>window).intlTelInputGlobals.getCountryData());


2.  另一種是在我們用到的component上宣告 declare  let window: any;

原本的程式碼就不用修改。



REF:

留言