1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

VeeValidateでこれだけあれば大体のフォームに対応できそうだ!と思われる書き方

Posted at

VeeValidateの4系でこれだけあれば大体のフォームに対応できそうなものを書いておきます。
かなりできることが多いのでこのやり方以外にもありそうですが、英語マニュアルが大変なので一旦下記にまとめます☺

template

エラーの制御としては大まかにこんな感じです。

  • ①各入力フィールドのチェック(正規表現などなど)
  • ②CGI、Pythonなどのサーバーサイドでのチェック(本件ではメールアドレスの重複チェック)
  • ③1つでもエラーが発生した場合の表示
  • ④確認画面に遷移してからのエラーバック対応
template
<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>

①各入力フィールドのチェック

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の値を合わせてください。

script
function validateName(val) {
  if (!val) {
    return '正しく入力してください';
  }
  const regex = /.+?(\x20|\u3000).*?[^\x20|\u3000]/;
  if (!regex.test(val)) {
    return '姓と名の間にスペース(半角/全角)を入力してください';
  }
  return true;
}

②CGI、Pythonなどのサーバーサイドでのチェック

template
<Form @submit="onSubmit" :initial-errors="errInitObj" v-slot="{ errors }">

@submit="onSubmit"
バリデーションチェックが全て問題なければ上記でonSubmit関数を実行し、ajaxでサーバー側でのバリデーションチェックを開始します。
:initial-errors="errInitObj" v-slot="{ errors }"
は、ここでは割愛。

script
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つでもエラーが発生した場合の表示

template
<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"
で初期エラーを表示できます。

template
<Form @submit="onSubmit" :initial-errors="errInitObj" v-slot="{ errors }">

------------

<p v-if="errInitObj.isError" class="error _02">入力に不備がございます内容をご確認ください</p>
script
const errInitObj = reactive(storeObj.$state.errInitObj)

今回はPiniaを使用しているのでerrInitObjは下記で保存して値を渡しています。

script(確認画面)
const json = await getJson(params)
// エラー発生
if (json.errorObj.isError) {
  storeObj.errorObjWrite(json.errInitObj)
  router.push({
    name: "form",
  });
}
Pinia
export const useStoreRegistry = defineStore('registry', {
  state: () => ({
    errInitObj: {
      isError: '',
      name: '',
      email: '',
    },
  }),
  actions: {
    errorObjWrite(errInitObj) {
      this.errInitObj = errInitObj;
    },
  },
});
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?