vee-validate v4を使ってComposion APIのコンポーネント内でバリデーションを実行する


Vue3のサポートを行なっている`vee-validate`のv4系を用いて Composition APIコンポーネントのバリデーション機能を実装する方法をまとめます。

# 開発環境
・フロントエンド
npm:6.12.1
node:12.13.1
yarn:1.21.1
Vue-cli:4.1.1
Vuetify:2.2.3
vee-validate: 4.2.4

# 参考

[VeeValidate](https://vee-validate.logaretm.com/v4/guide/composition-api/validation)

## vee-validateのインストール

記事執筆時点(2021/03/31)で最新のリリース版はv3系なので、必ず`next`を指定する必要があります。

```shell-session
$ yarn add vee-validate@next
```

## ログインフォームのバリデーション機能の実装

例題としてemailとpasswordを入力するログインフォームを想定します。

初めにフィールドとそれに紐付くバリデーションルール&エラーメッセージのスキームを作成します。

宣言した変数にemail,passwordというプロパティを用意します。
それぞれに(vee-validate内の)`GenericValidateFunction`という型のメソッドを設定します。

例題として、下記の様なバリデーションチェックを行うメソッドに引数の値を渡し、結果に応じたメッセージを返す様に設定します。

```TypeScript
import { useField, useForm } from 'vee-validate'

setup(){
    // checkTextLength()は引数valueの文字数をチェックするメソッド
    const loginSchema = {
      email(value: string): string {
        return checkTextLength(value) ? '' : 'This is required'
      },
      password(value: string): string {
        return checkTextLength(value) ? '' : 'This is required'
      }
    }
}
```

上記のスキームで実際にバリデーションを行う為にvee-validateから`useForm`と`useField`をimportしています。


- useForm():設定したスキームを基にしたフォームコンテキスト(フォームそのもの)を返す。
- useField():で個々のフィールドの値とエラーメッセージの変数を宣言する。

スキームと実際の画面で利用するフィールドの紐付けはコードで書くと下記の様になります。

1. 上記で作成したスキームをuseForm()の引数の`validationSchema`プロパティとして設定します。

2. バリデーションが実行される`email`と`password`用の値とエラーメッセージの変数をuseField()で宣言します。


```TypeScript
setup(){
    // 省略

    useForm({
      validationSchema: loginSchema
    })

    const { value: email, errorMessage: emailError } = useField<string>('email')
    const { value: password, errorMessage: passwordError } = useField<string>(
      'password'
    )
}
```

useField()で宣言されるバリデーション対象の変数は、`ref()`などを用いて宣言した時と同様に、リアクティブな変数となっています。(値を変更する為にvalueName.value = newValue　の様な書き方が必要。)

テキストフォームなどの単純なフィールドのケースの場合は下記の様にcomputedを設定して、v-modelに紐付ける様にすると良いでしょう。


```TypeScript

setup(){

    // 省略


    // computed
    const emailValue = computed({
      get: (): string => email.value,
      set: (value: string) => {
        email.value = value
      }
    })

    const passwordlValue = computed({
      get: (): string => password.value,
      set: (value: string) => {
        password.value = value
      }
    })

    return {
      emailValue,
      passwordlValue,
      emailError,
      passwordError
    }
}
```

下記の様にtemplateタグ内に設定するとスキームと画面への紐付けが出来ます。
これで、一通りのバリデーション機能を実装する事が出来ます。

```HTML
<div>
  <InputComponent
    name="email"
    type="text"
    v-model="emailValue"
  />
  <small class="p-error">{{ emailError }}</small>
</div>
<div>
  <InputComponent
    name="password"
    type="password"
    v-model="passwordlValue"
  />
  <span class="p-error">{{ passwordError }}</span>
</div>

```

![スクリーンショット 2021-03-31 2.46.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238861/7a27ad38-124f-62e4-680a-29aa2d4f23ad.png)


## 他のフィールドの値を参照したい場合

ユーザーの新規作成で確認用パスワードのチェックをしたい時などのケースです。
これはスキームで設定する`GenericValidateFunction`型のメソッドの第2引数から取得出来ます。
(第2引数は`FieldContext`型ですが、現在exportされていません。)

下記の様に、`第2引数.form.password`で`password`フィールドとして入力した値を取得出来ます。

```TypeScript

setup(){
  const sampleSchema = {
    password(value: string): string {
      return validatePassword(value)
    },
    confirmPassword(
      value: string,
      ctx: any
    ): string {
      return value === ctx.form.password ? '' : 'input same value!'
    }
  }
}
```

## 入力している値をリセットしたい場合

フォーム内の入力値や発生しているバリデーションエラーをまっさらにしたい場合です。

useForm()の戻り値を変数に格納し、`PublicFormContext`型の変数を設定します。

任意のタイミングで`PublicFormContext`型変数のhandleResetメソッドを実行するとフォームのリセットを行えます。

(`PublicFormContext`型の変数はフォームのsubmitのハンドリングも行えます。)



```TypeScript
  const formContext = useForm({
    validationSchema: sampleFormSchema
  })

  // 任意のタイミングで下記を実行させる
  formContext.handleReset()
```

自分がざっと調べてみた限りでですが、Vue3でのvee-validateの利用する方法は上記の通りになります。
色々と他に出来る事が多々ある為、より調べて行きたいと思います！