VeeValidateの4系でこれだけあれば大体のフォームに対応できそうなものを書いておきます。
かなりできることが多いのでこのやり方以外にもありそうですが、英語マニュアルが大変なので一旦下記にまとめます☺
template
エラーの制御としては大まかにこんな感じです。
- ①各入力フィールドのチェック(正規表現などなど)
- ②CGI、Pythonなどのサーバーサイドでのチェック(本件ではメールアドレスの重複チェック)
- ③1つでもエラーが発生した場合の表示
- ④確認画面に遷移してからのエラーバック対応
<template>
<main>
<article>
<Form @submit="onSubmit" :initial-errors="errInitObj" v-slot="{ errors }">
<section>
<div>
<dl>
<p v-if="errInitObj.isError" class="error">※入力に不備がございます。内容をご確認ください</p>
<div>
<dt><i class="req">必須</i>お名前</dt>
<dd>
<Field name="name" v-model="formObj.name" type="text" class="input_text" :rules="validateName" />
<ErrorMessage name="name" class="error" as="p" />
</dd>
</div>
<dt><i class="req">必須</i>メールアドレス </dt>
<dd>
<Field name="email" v-model="formObj.email" type="email" class="input_text"
:rules="validateEmail" />
<ErrorMessage name="email" class="error" as="p" />
</dd>
</div>
<div class="btn_box" v-if="Object.keys(errors).length">
<p class="error">
必要な情報が入力されていません。再度ご確認ください。
</p>
</div>
<div><button class="btn">確認画面へ</button></div>
</div>
</section>
</Form>
</article>
</main>
</template>
①各入力フィールドのチェック
<div>
<dt><i class="req">必須</i>お名前</dt>
<dd>
<Field name="name" v-model="formObj.name" type="text" class="input_text02" :rules="validateName" />
<ErrorMessage name="name" class="form_error" as="p" />
</dd>
</div>
:rules="validateName"
バリデーションチェックは関数化できちゃいます。
v-model="formObj.name"
入力値を復元する時に使用します。(setFieldValueでいけちゃうかもー)
<ErrorMessage name="name" class="form_error" as="p" />
エラーを表示します。nameの値を合わせてください。
function validateName(val) {
if (!val) {
return '正しく入力してください';
}
const regex = /.+?(\x20|\u3000).*?[^\x20|\u3000]/;
if (!regex.test(val)) {
return '姓と名の間にスペース(半角/全角)を入力してください';
}
return true;
}
②CGI、Pythonなどのサーバーサイドでのチェック
<Form @submit="onSubmit" :initial-errors="errInitObj" v-slot="{ errors }">
@submit="onSubmit"
バリデーションチェックが全て問題なければ上記でonSubmit関数を実行し、ajaxでサーバー側でのバリデーションチェックを開始します。
:initial-errors="errInitObj" v-slot="{ errors }"
は、ここでは割愛。
async function onSubmit(values, actions) {
//console.log(JSON.stringify(values, null, 2));
// メールアドレス重複チェック
const params = {
email: values.email,
};
// サーバー側と通信
const json = await getJson(params);
// all good
if (!json.errorObj.isError) {
// 保存して確認画面に遷移する的な処理は省略
return;
}
// set single field error
if (json.errorObj.email) {
// <ErrorMessage name="email" class="form_error" as="p" /> にエラーセット
actions.setFieldError('email', json.errorObj.email);
}
}
③1つでもエラーが発生した場合の表示
<Form @submit="onSubmit" :initial-errors="errInitObj" v-slot="{ errors }">
------略------
<div class="btn_box" v-if="Object.keys(errors).length">
<p class="error _02">
必要な情報が入力されていません。再度ご確認ください。
</p>
</div>
v-slot="{ errors }"
エラーが発生すると、errosにオブジェクトとして蓄積されるので、
Object.keys(errors).length
を条件としてエラーを表示します。
④確認画面に遷移してからのエラーバック対応
全てのバリデーションチェックをパスして、最後の登録直前でサーバーサイドエラーが発生した場合などに有効です。
:initial-errors="errInitObj"
で初期エラーを表示できます。
<Form @submit="onSubmit" :initial-errors="errInitObj" v-slot="{ errors }">
------略------
<p v-if="errInitObj.isError" class="error _02">※入力に不備がございます。内容をご確認ください</p>
const errInitObj = reactive(storeObj.$state.errInitObj)
今回はPiniaを使用しているのでerrInitObjは下記で保存して値を渡しています。
const json = await getJson(params)
// エラー発生
if (json.errorObj.isError) {
storeObj.errorObjWrite(json.errInitObj)
router.push({
name: "form",
});
}
export const useStoreRegistry = defineStore('registry', {
state: () => ({
errInitObj: {
isError: '',
name: '',
email: '',
},
}),
actions: {
errorObjWrite(errInitObj) {
this.errInitObj = errInitObj;
},
},
});