行動すれば次の現実

ほどよくモダンなシステム開発を目指しています。メインテーマは生産性、Ruby、Javascriptです。

input要素に入力した数字を3桁ごとのカンマ区切りにして表示する方法

input要素に入力した数字を3桁ごとのカンマ区切りにして表示する方法を説明します。 本記事はReactをベースに実装例を記述していますが、考え方は他のフレームワークでも同じですので、Reactを使用していない方も参考になるかと思います。

input type属性は「tel」がおすすめ

実装に入る前に前提知識として抑えておいてほしいポイントがあります。

それはinput type属性による入力制御の違いです。

input type="number"を使用することで数字のみが入力できるようになります。 モバイルの場合も同様に、数字のキーボードが表示されますので、ユーザビリティ的には問題有りません。

ただし今回のようにカンマ区切りされた数字は実質的には文字列と認識されますので、type="number"は使用できません。

そのため、input type="tel"を使用することおすすめします。 input type="tel"は、電話番号のように数字主体の文字列の入力を想定しています。

あくまでも入力できるのは文字列になりますが、type="text"との違いはモバイルの場合に数字のキーボードが表示されることです。

数字キーボード

以下に各input typeごとの挙動をまとめました。

input type 入力できる値 スマホ入力時 使用例
text 文字列 文字列キーボード 氏名
number 数字のみ 数字キーボード 年齢
tel 文字列 数字キーボード クレカ番号

具体的な実装例

上記の仕様を踏まえた上でtype="tel"を採用してサンプルプログラムを実装します。

サンプルではReactを使用していますが、onChangeのイベントハンドラ以外は他のフレームワークでも使用できるかと思います。

まずは、数字文字列に対して3桁ごとにカンマ区切りを適用させる関数を定義します。

function replaceFormatNumber(numberText) {
  if (!numberText) {
    return '';
  }
  return String(numberText).replace(/\d+/, function (m) {
    return m.replace(/(\d)(?=(?:\d{3})+$)/g, "$1,");
  });
}

次に、3桁区切りされた数字文字列をフラットな数字文字列に変換させる関数も定義します。

function replaceNumberText(formatNumber) {
  if (!formatNumber) {
    return '';
  }
  return formatNumber.replace(/,/g, '');
};

上記2つの関数を使用してonChangeイベントでstateを制御します。

handleChange(e) {
  let v = e.target.value;
  # カンマ区切りされた文字列をフラットな数字文字列に変換します
  v = String(replaceNumberText(v));
  # フラットな数字文字列に対してカンマ区切りを適用します
  v = replaceFormatNumber(v);
  # stateにセットします
  this.setState({[e.target.name]: v});
}

# render部分
<Input
  type="tel"
  name="number"
  value={number}
  onChange={this.handleChange}
/>