工作筆記:使用 JavaScript 控制輸入內容僅限於數字

總結

最近負責的產品在跑 QA 時才注意到 FireFox 瀏覽器「並不會限制 <input type="number"> 元件只能輸入數字內容」🤯!

為了實現「元件僅能允許使用者輸入數字」的需求,工程師要額外補上一些 JavaScript 來達成這個目的。這篇筆記會提供:

筆記

程式碼

限制使用者只能對一個 input 元件鍵入數字:

/* Function */
const onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  if (!/^\d*$/.test(e.target.value || '')) return;
  // TODO...
  // 已經確保使用者無法輸入非數字內容,剩下就根據實作需要來處理 e.target.value
};

/* Component */
<input value={userInput} onChange={onInputChange} />;

注意事項:不需要使用 <input type="number"> ,實測時發現 FireFox 的 <input type="number"> 無法正常觸發 onInputChange 效果,拔掉 type="number" 才能正常阻擋使用者鍵入數字以外的內容。可在 FireFox 開啟下方 code sand box 實測:

使用 type="number" 會讓手機裝置預設提供輸入數字用的虛擬鍵盤(參考下方引文),但為了能夠在 Firefox 也能限制使用者的輸入內容,最後還是決定拔掉 type="number" 的設定。

MDN: Mobile browsers further help with the user experience by showing a special keyboard more suited for entering numbers when the user tries to enter a value.


檢驗使用者輸入的內容是否為大於零的整數:

function isValidInteger(str: string) {
  return Number.isInteger(+str) && +str > 0;
}

注意不需要使用 Number.isSafeInteger() ,使用 isSafeInteger 會導致使用者在輸入過大的數字時產生錯誤。

MDN: The safe integers consist of all integers from -(2^53 - 1) to 2^53 - 1, inclusive (±9,007,199,254,740,991).

補充資訊

MDN: Logically, you should not be able to enter characters inside a number input other than numbers. Some browsers allow invalid characters, others do not; see Firefox bug 1398528.

FireFox 允許使用者對 type="number" 輸入數字以外的內容是個已知六年的 bug 🤷 但 browser compatibility 並沒有標註 FireFox 不支援 <input type="number">

參考文件