正数や小数のみ入力を許可するテキストボックスを 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
プロパティに保持しておいて、不正値が入力された場合は前回の正常値で上書きしている。泥臭い。
まとめ
どちらも最終的に泥臭い感じになりました...。もう少しスマートにしたいところ。
あと、今回初めて知ったのですが、KeyboardEvent
の keyCode
プロパティなど、割とよく使われているだろうと思われるプロパティがいつの間にか非推奨になっていました。代わりに key
や code
を使う模様。