【Vue.js】Buefyでvuelidateを使ってバリデーション
やること
Vueのアプリ開発にBuefyというBulmaベースのライブラリを使おうかと考えていますが、 フォームごとや複雑なバリデーションを想定するとデフォルト機能のバリデーションだと心もとないなので Vuelidateというバリデーション用のライブラリと組み合わせて使ってみます。
事前準備
vue-cli 3.0 の環境で作りました。
vue create my-app
Buefyのインストール
yarn add buefy
Vuelidateのインストール
yarn add vuelidate
main.js
import Vue from 'vue'; import Buefy from 'buefy'; import 'buefy/dist/buefy.css'; import Vuelidate from 'vuelidate'; Vue.use(Buefy); Vue.use(Vuelidate);
バリデーションを掛けるフォーム画面の作成
ログインページの想定で作ってみます。 (全量は下にあります。パスワードコンポーネントはbuefyデフォルトのものになっています)
Buefyのb-inputタグのカスタマイズ
ここでは必須(required)属性をサンプルとして実装してみます。
- デフォルトのバリデーション属性は使わないので、requiredは外します。
- 代わりに@blurでblur時のイベント発火(vuelidateのバリデーション起動)をセットします。
- b-fieldにはvuelidateのerror条件判定でtype,messageが表示されるように設定します。
- スクリプトの方はloginIdのバリデーション定義をいれています。
- vue-property-decoratorというライブラリを使っているのでそのまま使う場合はyarn等でインストールしてください。
<b-field :type="$v.loginId.$error ? 'is-danger': ''" :message="$v.loginId.$error ? 'this is validation message' : ''" > <b-input ref="loginId" v-model="loginId" placeholder="ログインID" @blur="$v.loginId.$touch" /> </b-field> 〜省略〜 <script> import { Component, Vue } from 'vue-property-decorator'; import { validationMixin } from 'vuelidate'; import { required, maxLength } from 'vuelidate/lib/validators'; @Component({ mixins: [validationMixin], validations: { loginId: { required, minLength: maxLength(30) }, password: { required, minLength: maxLength(30) } } }) export default class Login extends Vue { loginId = ''; password = ''; error = false; 〜省略〜
まとめ
こんな感じでVuelidateと連携できるはずです!
Vuelidateだとthis.$v.$touch()を使ってのフォーム全体のバリデーション発火やthis.$v.$errorでの状態チェックが便利ですね!
Login.vue
<template> <section class="hero is-fullheight is-primary is-bold"> <div class="hero-body"> <div class="container has-text-centered"> <h1 class="title">TITLE</h1> <p class="subtitle">SUB</p> <div class="column is-4 is-offset-4"> <div class="box"> <b-field :type="$v.loginId.$error ? 'is-danger': ''" :message="$v.loginId.$error ? 'this is validation message' : ''" > <b-input ref="loginId" v-model="loginId" placeholder="ログインID" maxlength="30" @blur="$v.loginId.$touch" /> </b-field> <b-field> <b-input ref="password" v-model="password" placeholder="パスワード" required type="password" maxlength="30" password-reveal/> </b-field> <a :class="{ 'is-loading': loading }" class="button is-fullwidth is-primary" type="submit" @click="hoge()">LOGIN</a> </div> </div> </div> </div> </section> </template> <script> import { Component, Vue } from 'vue-property-decorator'; import { validationMixin } from 'vuelidate'; import { required, maxLength } from 'vuelidate/lib/validators'; @Component({ mixins: [validationMixin], validations: { loginId: { required, minLength: maxLength(30) }, password: { required, minLength: maxLength(30) } } }) export default class Login extends Vue { loginId = ''; password = ''; error = false; loading = false; hoge() { this.$v.$touch(); } } </script>