Nuxt+Buefy+VueValidate+TypeScript
ひさびさにVeeValidateを見てみたら、
使いやすくなっていた気がするので、いろいろ調べたときの備忘録。
インストール
$ npm i vee-validate
tsconfig.json
メッセージファイルがjsonなので、
tsconfig.json
に設定を追加。
{ "compilerOptions": { "resolveJsonModule": true, // 追加 "esModuleInterop": true, // 追加 } } }
plugins/vue-validate.ts
VueValidateでは、バリデーションのルールは用意されているが、
設定しないと利用できない。
・Available Rules | VeeValidate
なので、pluginsで初期設定する。
// plugins/vee-validate import Vue from "vue"; import { ValidationProvider, ValidationObserver, extend, localize } from "vee-validate"; import { required, email } from "vee-validate/dist/rules"; import ja from "vee-validate/dist/locale/ja.json"; // 利用するルールの設定 extend("required", required); extend("email", email); // メッセージの日本語化 localize("ja", ja); // コンポーネントの登録 Vue.component("ValidationProvider", ValidationProvider); Vue.component("ValidationObserver", ValidationObserver);
全ルールをインポートする場合は、こんな感じ。
import { extend } from 'vee-validate'; import * as rules from 'vee-validate/dist/rules'; // with typescript for (let [rule, validation] of Object.entries(rules)) { extend(rule, { ...validation }); }
nuxt.config.tsの設定
作ったプラグインを反映。
// nuxt.config.ts import { NuxtConfig } from "@nuxt/types"; const config: NuxtConfig = { plugins: [ "~/plugins/vee-validate" ], } export default config;
使い方
全体はこんな感じ。
<template> <ValidationObserver ref="observer" v-slot="{ handleSubmit, valid }" slim> <form @submit.prevent=""> <fieldset :disabled="loading"> <ValidationProvider rules="required|email" name="メールアドレス" v-slot="{ errors, valid }" slim > <b-field label="メールアドレス" :type="{ 'is-danger': errors[0], 'is-success': valid }" :message="errors" > <b-input type="text" v-model="email" /> </b-field> </ValidationProvider> <ValidationProvider rules="required" name="パスワード" v-slot="{ errors, valid }" slim > <b-field label="パスワード" :type="{ 'is-danger': errors[0], 'is-success': valid }" :message="errors" > <b-input type="password" v-model="password" /> </b-field> </ValidationProvider> <b-field> <div class="control"> <button type="submit" class="button is-primary" :class="{ 'is-loading': loading }" :disabled="!valid" @click="handleSubmit(submit)" > ログイン </button> </div> </b-field> </fieldset> </form> </ValidationObserver> </template> <script lang="ts"> import { Component, Vue, Prop } from "nuxt-property-decorator"; @Component export default class LoginForm extends Vue { private loading: boolean = false; private email: string = ""; private password: string = ""; private submit() { if (!!this.loading) return; const data = { email: this.email, password: this.password, }; this.$emit("submit", data); } } </script>
1. Form全体をValidationObserverで囲む
<ValidationObserver ref="observer" v-slot="{ handleSubmit, valid }" slim> <form @submit.prevent=""> <fieldset :disabled="loading"> <!-- 略 --> <b-field class="mt-5"> <div class="control is-expanded"> <button type="submit" class="button is-primary" :class="{ 'is-loading': loading }" :disabled="!valid" @click="handleSubmit(submit)" > ログイン </button> </div> </b-field> </fieldset> </form> </ValidationObserver>
ポイントは以下の2つ
submit
で実行したい関数を、handleSubmit
でラップvalid
なときにしか呼び出されない
- バリデーションの結果は、
valid
で渡される
・Validation Observer | VeeValidate
2. 各フィールドをValidationProviderで囲む
各項目のバリデーションは、ValidationProvider
で設定する。
<ValidationProvider rules="required|email" name="メールアドレス" v-slot="{ errors, valid }" slim > <b-field label="メールアドレス" :type="{ 'is-danger': errors[0], 'is-success': valid }" :message="errors" > <b-input type="text" v-model="email" /> </b-field> </ValidationProvider>
- バリデーションルールは、
ValidationProvider
のrules
に設定- 今回は必須とEmail形式
ValidationProvider
のname
に、項目名を設定できる- 「メールアドレスは必須入力です」みたいに使われる
errors
には、エラーになったルールのメッセージが入ってるvalid
は、エラーがないとtrue
slim
をつけると、<span>
で囲われなくなる
デフォルトでは、<ValidationObserver>
や<ValidationProvider>
は、<span>
に置き換えられる。
Buefyの場合だと、cssが効かなくなってしまうので、あまりうれしくない。。
直接、slotの要素だけを描画して欲しいときは、slim
オプションをつければOK。
・Validation Provider | VeeValidate
・Validation Observer | VeeValidate
ただ、Vue2の制約で<template>
のルートは1つなので、
こんな感じになっているとNG。
<template> <ValidationObserver slim> <form /> <form /> </ValidationObserver> </template>
ちゃんと一つの要素だけになるようにしないといけない。
<template> <ValidationObserver slim> <form /> </ValidationObserver> </template>
以上!!