要件そのものにどうも納得がいかなかいが世の中似たような事求められることもありそうだからメモ。
##要件
- フロントエンドでリアルタイムに入力項目にバリデートをかけたい
- 条件外の入力文字列はそもそも入力できないようにしたい
- フレームワークはVue.js
##検討
- とりあえずは
pattern
が使えそう - (2)が無ければ
input
のpattern
に正規表現を入れてイチイチform
タグで囲って入力毎にsubmit
してやれば大体イケそうだが - vue-validator使えば多分イケるだろうけどこの程度のことに導入したくない
##現時点での結論:
@inputでプロパティとvalueの両方に代入する
<template>
<main id="app"><main id="app">
<h1>Vueでシンプルな入力制限</h1>
<table>
<tbody>
<tr>
<th>数字のみ:</th><td><input type="text" pattern="^[0-9]+" maxlength="20" :value="test1" @input="test1=opt(test1,$event)"></td>
</tr>
</tbody>
</table>
</main>
</template>
<script>
var vue = new Vue({
el:'#app',
data:{
test1:'',
},
methods:{
opt:function(e){
var re = new RegExp(e.target.pattern);
var result = re.exec(e.target.value);
return e.target.value = (result)?result[0]:oldVal;
}
}
})
</script>
-
v-model
はv-bind:value
とv-on:input
の糖衣構文 - インライン構文でプロパティに代入すると
dispatchEvent
しなくて良くてスマートな感じ
##失敗:カスタムディレクティブ
カスタムディレクティブ
<template>
<main id="app">
<table>
<tbody>
<tr>
<th>数字のみ:</th><td><input type="text" pattern="^[0-9]+" maxlength="10" v-model="test1" v-validate="test1"></td>
</tr>
</tbody>
</table>
</main>
</template>
<script>
var vue = new Vue({
el:'#app',
directives:{
validate:function(el, binding, vnode){
var re = new RegExp(e.target.pattern);
var result = re.exec(binding.value);
el.value = (result)?result[0]:'';
var evt = document.createEvent("HTMLEvents"); // この辺が冗長でアホくさい
evt.initEvent('input', true, true );
el.dispatchEvent(evt);
}
}
});
</script>
- 値をプロパティに直接入れたいが、
binding.value
は読み取り専用 -
binding.arg
とかbinding.expression
とかでプロパティ名を取ることは可能だが、v-for
の中だったりするとどうしようもなくなる - と言ってelのvalueに値を代入してもイベントが起こらないから態々起こさないといけない。
- これが非常に冗長で美しくない。
##DEMO
Vueでシンプルな入力制限 http://jsdo.it/hadakadenkyu/22SK/