【Vue3】[vuelidate]Uncaught TypeError: Cannot read properties of undefined (reading ‘name’)のエラー対処

以下、作業用メモです。

Vuelidateを使って、バリデーション機能を実装した際に、タイトルのようなエラーに遭遇しました。ブラウザ表示されず、コンソールにエラー表示されていました。

具体的にエラーが出ている箇所は、以下の部分。

<div v-if="v$.form.name.$error">氏名は必須です。</div>

エラーメッセージから判断すると、v$.form.nameundefinedであるという問題が発生。
これは、v$オブジェクトまたはそのformプロパティ、あるいはnameプロパティが定義されていないことを示している。

Vuelidateのバージョン2では、バリデーションルールを適用するための新しい構文が導入されています。
それにより、v$オブジェクトの構造が変わり、v$.form.nameの代わりにv$.name.$errorのように直接フィールドにアクセスすることが可能になったそうです。そのため、v$.name.$error のようにして、直接フィールドにアクセスするように修正すれば、問題なく表示されました。

<script setup>
import { ref } from 'vue'
import { useVuelidate } from '@vuelidate/core'
import { required } from '@vuelidate/validators'

const form = ref({
  name: '',
  email: '',
  body: ''
})

const rules = {
  name: { required },
  email: { required },
  body: { required }
}

const v$ = useVuelidate(rules, form)

const submit = () => {
  v$.$validate()
  if (v$.$error) {
    return
  }
  // バリデーションが通った後の処理をここに書く
}
</script>

<template>
  <form @submit.prevent="submit">
    <div>
      <label>氏名:</label>
      <input v-model="form.name" type="text" />
      <div v-if="v$.name.$error">氏名は必須です。</div>
    </div>
    <div>
      <label>メール:</label>
      <input v-model="form.email" type="text" />
      <div v-if="v$.email.$error">メールは必須です。</div>
    </div>
    <div>
      <label>本文:</label>
      <textarea v-model="form.body"></textarea>
      <div v-if="v$.body.$error">本文は必須です。</div>
    </div>
    <button :disabled="v$.$invalid">送信</button>
  </form>
</template>

【その他メモ】

・メッセージではなくバリデーションエラーが発生しているかどうかは$v.value.$errorで確認することができる。

・$validate関数はバリデーションの結果をboolenで戻しますがPromiseで戻されるため結果を取得するためにはasync, await関数を利用する必要がある。

・エラーメッセージ表示時の以下のバイディングの意味について。

  :class="{ error : $v.name.$error,'form-control': true }"

「form-controlクラスを常に適用し、nameフィールドがバリデーションエラーを持っている場合にはerrorクラスも適用する」という意味になる。これにより、バリデーションエラーの有無に応じて要素のスタイルを動的に変更することが可能になる。

【参考サイト】

以下のサイトはいろいろなバリデーションの実例も載ってて参考になりました。

☆☆☆エラーメッセージを表示する方法も解説してくれている
☆☆☆

この記事を書いた人