正数や小数のみ入力を許可するテキストボックスコンポーネント

正数や小数のみ入力を許可するテキストボックスを Vue.js のコンポーネントとして作ってみました。一般的には type="number" を使うといいのかもしれませんが、今回はもろもろの事情により type="text" を使います。あと、Vue.js らしいところはあまりないです...。

サンプルコード

正数のみ入力を許可するテキストボックス

テンプレートは次の通り。

template: `
  <input type="text" :size="size" :maxlength="maxlength" v-model="value" @keypress="validate" @input="value=format(value)" />
`

@keypress@input で制御する。イベントハンドラは次の通り。

methods: {
  validate (e) {
    const charCode = (e.which) ? e.which : e.keyCode
    if (charCode > 31 && (charCode < 48 || charCode > 57)) { // 数字入力のみ許可する
      e.preventDefault()
    } else {
      return true
    }
  },
  format (val) {
    if (!val) {
      return ''
    }
    const replaced = val.replace(/\D/g, '') // 数字以外を除去
    return replaced ? replaced : ''
  }
}

@keypress では、keyCode で数字入力のみ許可するようにしている。ただし、これだと IME の入力が制御できない。仕方がないので、@input で数字以外を除去して上書き。泥臭い。

正数と小数のみ入力を許可するテキストボックス

テンプレートは次の通り。

template: `
  <input type="text" :size="size" :maxlength="maxlength" v-model="value" @keypress="validate" @change="value=format(value)" />
`

こちらは @keypress@change で制御する。イベントハンドラは次の通り。

methods: {
  validate (e) {
    const charCode = (e.which) ? e.which : e.keyCode
    if ((charCode > 31 && (charCode < 48 || charCode > 57)) && charCode !== 46) { // 数字と小数点の入力のみ許可する
      e.preventDefault()
    } else {
      return true
    }
  },
  format (val) {
    if (!val) {
      return this.prevValue = ''
    }
    if (/^([1-9]{1}[0-9]{0,1})(\.\d{0,2})?$/.test(val)) { // ##.##
      return this.prevValue = val
    }
    if (/\.\d{3,}$/.test(val)) { // .### => .##
      return this.prevValue = (Math.floor(parseFloat(val) * Math.pow(10, 2)) / Math.pow(10, 2)).toString()
    }
    return this.prevValue
  }
}

@keypress では、keyCode で数字と小数点の入力のみ許可するようにしている。今回、整数部2桁&小数第2位という形式で制限している。@input だと厳しい感じだったので、@change でフォーカスが外れたタイミングでチェックしている。前回の正常値を data プロパティに保持しておいて、不正値が入力された場合は前回の正常値で上書きしている。泥臭い。

まとめ

どちらも最終的に泥臭い感じになりました...。もう少しスマートにしたいところ。

あと、今回初めて知ったのですが、KeyboardEventkeyCode プロパティなど、割とよく使われているだろうと思われるプロパティがいつの間にか非推奨になっていました。代わりに keycode を使う模様。

developer.mozilla.org