先日、フロントサイドのバリデーションにはvalidatorjsが便利という記事を拝見し、現在作っているシステムで使ってみようとしたのですが、挫折しました。
理由としては、複雑なフロントを作ろうとしているためで、下記の要件を満たす必要がありました。
- 1:n のデータで、ユーザーが追加できる要素がある (例: 複数メールアドレス登録)
- ページローティング直後はバリデーションしない
- ユーザーがインプット開始時に、 入力中の要素のみ バリデーション
- フォームを送信する直前に 全ての要素 に対してバリデーション
- エラーのある要素は赤くする
- エラーのある 要素の直後 に、 「メールアドレスは必須項目です。」などというメッセージを表示
- バリデーションのルールは一箇所にまとめたい。入力中と送信時でほぼ使いまわしたい。
そこで見つけたのが VeeValidate
です。
素晴らしかったので使い方を書いておきます。
単純なバリデーション
Emailを送信するフォームがあって、下記のタイミングでバリデーションが働くようにします。
- 入力時
- 送信時
Promiseでできるのが気持ちいいですね。またバリデーションのルールを <input>
に置けるのが個人的には好きです。
VeeValidationSimple.vue
<template>
<div>
<input
name="email"
v-model="email"
v-validate="'required|email'"
:class="{'has-error': errors.has('email')}">
<p v-if="errors.has('email')" class="alert-danger">
{{ errors.first('email') }}
</p>
<button @click="register">Register</button>
</div>
</template>
<script>
import Vue from 'vue'
import VeeValidate from 'vee-validate'
Vue.use(VeeValidate)
export default {
data () {
return {
email: ''
}
},
methods: {
register () {
this.$validator.validateAll().then((result) => {
if (!result) {
alert(this.errors.all())
return
}
alert('Hello, ' + this.email)
})
}
}
}
</script>
<style>
.alert-danger {
color: red;
}
.has-error {
border-color: red;
}
</style>
複数の要素に対するバリデーション
意外と簡単でした。
name
で識別しているらしいので、関連する属性値に連番を振ってあげればOKです。
VeeValidationMultiple.vue
<template>
<div class="hello">
<!-- 要素に連番を振る -->
<div v-for="(account, i) in accounts">
<input
:name="'email' + i"
v-model="account.email"
v-validate="'required|email'"
:class="{'has-error': errors.has('email' + i)}">
<p v-if="errors.has('email' + i)" class="alert-danger">
{{ errors.first('email' + i) }}
</p>
</div>
<p>
<button @click="addAccount">Add Account</button>
<button @click="register">Register</button>
</p>
</div>
</template>
<script>
import Vue from 'vue'
import VeeValidate from 'vee-validate'
Vue.use(VeeValidate)
export default {
data () {
return {
// v-forで回す要素は、オブジェクトの配列にする
accounts: [{
email: ''
}]
}
},
methods: {
// 追加
addAccount () {
this.accounts.push({
email: ''
})
},
register () {
this.$validator.validateAll().then((result) => {
if (!result) {
alert(this.errors.all())
return
}
alert('Hello, ' + this.accounts)
})
}
}
}
</script>
<style>
.alert-danger {
color: red;
}
.has-error {
border-color: red;
}
</style>
こんな感じになります。
ちゃんと、後から追加された要素に対してもバリデーションが効いています。
参考
- https://m.dotdev.co/form-validation-using-vue-js-2-35abd6b18c5d
- http://vee-validate.logaretm.com/index.html
ドキュメントも豊富です。
今回のソースコードも貼っておきます。
https://github.com/acro5piano/vue-cli-test/blob/master/src/components/VeeValidation.vue