電話番号の登録フォームにまさかnumber型を使ってないよね？

# はじめに
こんにちは、[まつけん](https://twitter.com/matsuken_web314)です。
「ユーザーが電話番号を登録するフォーム」って、よくありますよね？
↓こういうの↓

![スクリーンショット 2024-09-14 10.17.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1584967/f02df245-da17-58c7-c225-f2ea0709bd6a.png)
↑このHTMLのフォーム要素に`<input type="number"> `を使ってたりしませんか？

結論、ダメ :ng: なので解決策とセットで解説します。


# 問題

:::note alert
`<input type = "number">`を電話番号フォームに使ってはダメな理由
- 先頭の0が消える可能性がある
- 電話番号は国番号をつける場合があり、+81901111222のように数字以外も入る可能性がある
:::

### 問題1:先頭の0が消える可能性がある


- `<input type="number">`に先頭が0から始まる番号を入力すると、一部のブラウザ(Firefox)で0が消されて表示される
  - 参考：[🙅先頭がゼロから始まる番号の入力欄には使わない](https://catnose.me/learning/html/input-number) 
- 先頭の0が不要なものとして削除される場合もある
- 数値を打ち込んでからトグルボタン（▲▼）を押すと0が消える


実際に先頭0の数値（例：0901234）を打ち込んでからトグルボタン（▲▼）を押すと0が消えるので、ぜひお試しあれ

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ZEdZdgY" data-pen-title="誤った電話番号登録フォーム" data-user="matsuken314" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/matsuken314/pen/ZEdZdgY">
  誤った電話番号登録フォーム</a> by matsuken314 (<a href="https://codepen.io/matsuken314">@matsuken314</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

▼先頭の0が消えている
![画面収録 2024-09-14 12.07.01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1584967/fe8d25b2-6e21-cf32-d17e-1caf973150a3.gif)


### 問題2:電話番号は数字以外も入る可能性がある

電話番号は国番号をつける場合があり、数字以外も入る可能性があります。
例えば、「+81901111222」など
`number`型は半角の数字のみ許容するため、「+」などの文字を扱えません。

### 実際に起きたこと (少しボヤかしてます)
 以下要件の「電話番号登録フォーム」の実装でのコードレビュー時
 - 文字列は受けつけない（半角数字のみ）
 - 9ケタ〜14ケタまでしか受けつけない
<br>

> `<input type="number"> `を使って、実装してたら

**先輩エンジニア**:
「こちらの対応時に入力を type="number" で文字列を入力出来ないようにした意図が知りたいです。」

**自分**:
『サーバーサイドでも「文字列は受け付けず、半角数字のみ」という制限をかけてましたが、
追加でフロントに「半角数字のみしか受け付けない」制限にすればより強固なバリデーションになると思ったからです』

**先輩エンジニア**:
「HTMLでも`<input type="tel">` のように電話番号用のinputタイプがあると思うので、

- 文字列は受けつけない（半角数字のみ）
- 9ケタ〜14ケタまでしか受けつけない

であれば、patern属性に正規表現でバリデーションかけて
```html
input type="tel" name="tel" pattern="[0-9]{9,14}" required>
```
でも実現できると思います」


**自分**:
「`<input type="tel">`を使った方が良いこととその理由まで教えていただきありがとうございます！」

# 解決方法 

:::note
**結論**
- `<input type="tel">`を使う
- 文字列が入力できない制限（半角数字のみ許容）については`pattern`属性と組み合わせて利用する
:::



↓下の「Result」タブを押すと、実際のフォームで操作できます


<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="GRbLbwQ" data-pen-title="正しい電話番号登録フォーム" data-user="matsuken314" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/matsuken314/pen/GRbLbwQ">
  正しい電話番号登録フォーム</a> by matsuken314 (<a href="https://codepen.io/matsuken314">@matsuken314</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>



**【解説】**
```html
<input type="tel" pattern="[0-9]{9,14}" required>
```

とすることで、
- 文字列は受けつけない（半角数字のみ）
- 9ケタ〜14ケタまでしか受けつけない

を実現しています

# おわりに
学びとして、数値だから`<input type="number">`を安易に使用するのはダメだと分かりました。

[MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/number#number_%E5%85%A5%E5%8A%9B%E6%AC%84%E3%81%AE%E4%BD%BF%E7%94%A8)では
`<input type="number">`の使用基準として、
> スピンボタン（▲▼）の増減が使い勝手として有益な場合に使う方がいい

と書かれてます。
具体例として
「購入チケットの数を入力してください」のフォームが紹介されてます。

改めて、
「ユーザーがどういった目的でこの機能を使うのか」
を考え抜いて実装しないといけない教訓になりました。

丁寧に教えてくれた先輩エンジニアの方に感謝です。

# 参考
https://note.com/takamoso/n/n79df2d8f16bf#apcFz

https://catnose.me/learning/html/input-number

https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/number#number_%E5%85%A5%E5%8A%9B%E6%AC%84%E3%81%AE%E4%BD%BF%E7%94%A8

- 先輩エンジニアのレビュー :bow: