🍥

【Vue.js】VeeValidate4のFieldArrayへVuetifyのコンポーネントを入れ込む

2022/01/18に公開

概要

VeeValidateは、Vue.jsで用意されているバリデーションのライブラリです。VeeValidateでは可変の配列の入力項目(FieldArray)に対して、チェックをかけることもできます。今回はFieldArrayにVutifyのコンポーネントを入れてチェックをかける実装を紹介します。
なお、前提としてVeeValidateのバージョンは4、Vuetifyのバージョンは3(2022年1月時点でアルファ版)を使用するものとします。

対応方法

  • 配列項目の制御には、VeeValidateのuseFieldArrayを使用します。こちらで、フィールドと追加や削除時のメソッドを取得します。
  • 配列のバリデーションには、こちらのドキュメントに実装例がある通り、yupを使用します。
  • Vutifyのコンポーネントに値を受け渡すには、こちらのドキュメントにある通り、Fieldのv-slotで得られるfileldの項目を、v-bindに設定します。

実装サンプル

例として、サイト名とURLを可変で入力できる「参考URL」の項目を実装します。

<template>
  <span>
    参考URL
    <v-btn
      class="ml-2 mb-1"
      icon
      width="20"
      height="20"
      color="indigo"
      @click="pushUrlExec"
    >
      <v-icon>mdi-plus</v-icon>
    </v-btn>
    <fieldset v-for="(field, idx) in urlFields" :key="idx">
      <br />
      <ErrorMessage :name="`referenceUrls[${idx}].siteName`" class="error" />
      <Field
        :id="`siteName_${idx}`"
        :name="`referenceUrls[${idx}].siteName`"
        v-slot="{ field }"
      >
        <v-text-field
          v-bind="field"
          label="サイト名"
          style="width: 270px"
        ></v-text-field>
      </Field>
      <ErrorMessage :name="`referenceUrls[${idx}].url`" class="error" />
      <Field
        :id="`referenceUrls_${idx}`"
        :name="`referenceUrls[${idx}].url`"
        v-slot="{ field }"
      >
        <v-text-field
          v-bind="field"
          label="URL"
          style="width: 270px"
        ></v-text-field
      ></Field>
      <v-btn
        class="ml-2 mb-1"
        icon
        width="20"
        height="20"
        color="indigo"
        @click="
          () => {
            removeUrlExec(idx);
          }
        "
      >
        <v-icon>mdi-minus</v-icon>
      </v-btn>
    </fieldset>
  </span>
</template>

<script>
import { defineComponent } from "vue";
import { useFieldArray, useForm, ErrorMessage, Field } from "vee-validate";
import * as yup from "yup";

export default defineComponent({
  components: {
    ErrorMessage,
    Field,
  },
  setup() {
    // 入力フォームのバリデーション
    const postRegisterSchema = yup.object({
      referenceUrls: yup
        .array()
        .of(
          yup.object().shape({
            siteName: yup.string().required("サイト名を入力してください"),
            url: yup.string().required("urlを入力してください"),
          })
        )
        .strict(),
    });
    const formContext = useForm({
      validationSchema: postRegisterSchema,
    });

    // urlの配列項目
    const {
      remove: removeUrl,
      push: pushUrl,
      fields: urlFields,
    } = useFieldArray("referenceUrls");

    const pushUrlExec = () => {
      pushUrl({ siteName: "", url: "" });
    };

    const removeUrlExec = (idx) => {
      removeUrl(idx);
    };

    return {
      urlFields,
      pushUrlExec,
      removeUrlExec,
    };
  },
});
</script>

表示イメージは下記のようになります。

Discussion