vee-validateのエラーが出ているので、vee-validate4を導入して、コードを修正します。
前回:Nuxt BridgeをNuxt3に移行。先ずはVuetifyでページが表示される所まで
- vee-validate4を導入
- vee-validate4の変更点
- メッセージカスタマイズ
- [Vue warn]: Runtime directive used on component with non-element root node.
- 【次回】$axiosをFetch APIに書き換える
- 今回のコミット内容
[plugin:vite:import-analysis] Failed to resolve import “vee-validate” from “pages/users/sign_in.vue”. Does the file exist?
vee-validate4を導入
【公式】VeeValidate – Form
GitHub – logaretm/vee-validate: ✅ Painless Vue forms
-> MIT license
Packageを追加
% yarn add -D vee-validate @vee-validate/rules @vee-validate/i18n
使用しているPageやComponentを修正
※v-bindだけだと、変更画面の初期値が表示されなくなるのでv-modelに戻しました。
v-model=”field.value”でもOKなのですが、
v-file-inputは、エラー(下記)になるので、定義を揃えておく事にしました。
[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core Uncaught (in promise) DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string. Uncaught (in promise) TypeError: Cannot read properties of null (reading 'emitsOptions')
vue.js – vee-validate + vuetify text input field → how to migrate to new versions? – Stack Overflow
pages/users/sign_up.vue
- <validation-observer v-slot="{ invalid }" ref="observer">
+ <Form v-slot="{ meta }" ref="form">
<v-form autocomplete="on">
<v-card-title>アカウント登録</v-card-title>
<v-card-text>
- <validation-provider v-slot="{ errors }" name="password_confirmation" rules="required|confirmed_password:password">
+ <Field v-slot="{ errors }" v-model="query.password_confirmation" name="password_confirmation" rules="required|confirmed_password:@password">
<v-text-field
+ v-bind="field"
v-model="query.password_confirmation"
:type="showPassword ? 'text' : 'password'"
label="パスワード(確認)"
prepend-icon="mdi-lock"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
autocomplete="new-password"
counter
:error-messages="errors"
@input="waiting = false"
@click:append="showPassword = !showPassword"
/>
- </validation-provider>
+ </Field>
<v-btn
id="sign_up_btn"
color="primary"
class="mt-4"
- :disabled="invalid || processing || waiting"
+ :disabled="!meta.valid || processing || waiting"
@click="postSingUp()"
>
登録
</v-btn>
- </validation-observer>
+ </Form>
<script>
- import { ValidationObserver, ValidationProvider, extend, configure, localize } from 'vee-validate'
- import { required, email } from 'vee-validate/dist/rules'
+ import { Form, Field, defineRule, configure } from 'vee-validate'
+ import { localize, setLocale } from '@vee-validate/i18n'
+ import { required, email, min, max, confirmed } from '@vee-validate/rules'
+ import ja from '~/locales/validate.ja' // 標準のメッセージを使うなら'@vee-validate/i18n/dist/locale/ja.json'
- extend('required', required)
- extend('email', email)
- extend('min', min)
- extend('max', max)
- extend('confirmed_password', confirmed)
+ defineRule('required', required)
+ defineRule('email', email)
+ defineRule('min', min)
+ defineRule('max', max)
+ defineRule('confirmed_password', confirmed)
- configure({ generateMessage: localize('ja', require('~/locales/validate.ja.js')) })
+ configure({ generateMessage: localize({ ja }) })
+ setLocale('ja')
export default {
components: {
- ValidationObserver,
- ValidationProvider,
+ Form,
+ Field,
- this.$refs.observer.setErrors(error.response.data.errors)
+ this.$refs.form.setErrors(error.response.data.errors)
vee-validate4の変更点
- validation-observer -> Form
- validation-provider -> Field, v-modelで値を渡す必要がある。
v-bind=”field”で元のと紐付ける - invalidは廃止されている。validは空が返ってくる。!meta.validに変更
- extend -> defineRule
- localizeは@vee-validate/i18nに移動している。setLocaleしないとenになる
- Field rulesの参照が@始まりに変更。例: “confirmed:@password”
メッセージカスタマイズ
こちらも折角なので、tsに変更します。(jsonでも良いけど、コメントアウトできない)
vee-validate4では、キーやメッセージの表記が変わっているので注意。
- _default, url -> 追加
- excluded -> not_one_of、oneOf -> one_of
- is_not, double -> 削除
- {field} -> {_field_}
- {min} -> 0:{min}, {max} -> 1:{max}, 0:{length}, 0:{width}, 1:{height}, 0:{size}
locales/validate.ja.js -> .ts
- module.exports = {
- messages: {
+ const code = 'ja'
+ const messages = {
- <元のメッセージ>
+ <↓変更後のメッセージ> ※confirmed_password/confirmed_new_password/size_20MBは追加しています。
// _default: '{field}は有効な値ではありません',
// alpha: 'アルファベットのみで入力してください。', // "{field}はアルファベットのみ使用できます",
// alpha_num: '英数字のみで入力してください。', // "{field}は英数字のみ使用できます",
// alpha_dash: '英数字とハイフン・アンダースコアのみで入力してください。', // "{field}は英数字とハイフン、アンダースコアのみ使用できます",
// alpha_spaces: 'アルファベットと空白のみで入力してください。', // "{field}はアルファベットと空白のみ使用できます",
// between: '0:{min}から1:{max}の値を入力してください。', // "{field}は 0:{min} から 1:{max} の間でなければなりません",
// confirmed: '致していません。', // "{field}が一致しません",
confirmed_password: 'パスワードと一致していません。',
confirmed_new_password: '新しいパスワードと一致していません。',
// digits: '0:{length}桁の数字を入力してください。', // "{field}は 0:{length}桁の数字でなければなりません",
// dimensions: '幅0:{width}px、高さ1:{height}px以下にしてください。', // "{field}は幅 0:{width}px、高さ 1:{height}px 以内でなければなりません",
email: '形式が正しくありません。', // "{field}は有効なメールアドレスではありません",
// not_one_of: '値が正しくありません。', // "{field}は不正な値です",
// ext: 'このファイルには対応していません。', // "{field}は有効なファイル形式ではありません",
// image: 'この画像には対応していません。', // "{field}は有効な画像形式ではありません",
// integer: '整数のみで入力してください。', // "{field}は整数のみ使用できます",
// is: '致していません。', // "{field}が一致しません",
// length: '0:{length}文字で入力してください。', // "{field}は 0:{length} 文字でなければなりません",
// max_value: '0:{max}以下を入力してください。', // "{field}は 0:{max} 以下でなければなりません",
max: '0:{length}文字以下で入力してください。', // "{field}は 0:{length} 文字以内にしてください",
// mimes: 'このファイルには対応していません。', // "{field}は有効なファイル形式ではありません",
// min_value: '{min}以上を入力してください。', // "{field}は 0:{min} 以上でなければなりません",
min: '0:{length}文字以上で入力してください。', // "{field}は 0:{length} 文字以上でなければなりません",
// numeric: '正数を入力してください。', // "{field}は数字のみ使用できます",
// one_of: '有効な値を入力してください。', // "{field}は有効な値ではありません",
// regex: '形式が正しくありません。', // "{field}のフォーマットが正しくありません",
required: '入力してください。', // "{field}は必須項目です",
// required_if: '入力してください。', // "{field}は必須項目です",
// size: '0:{size}KB以下のファイルを選択してください。', // "{field}は 0:{size}KB 以内でなければなりません",
size_20MB: '20MB以下のファイルを選択してください。'
// url: '形式が正しくありません。' // "{field}は有効なURLではありません"
}
+ export default {
+ code,
+ messages
+ }
[Vue warn]: Runtime directive used on component with non-element root node.
[Vue warn]: Runtime directive used on component with non-element root node. The directives will not function as intended.
Fieldでv-ifは使えましたが、v-showだとwarnが出て動かないので、spanやdivで囲みます。
- <Field v-show="tabDescription === 'input'" v-slot="{ errors }" v-model="space.description" name="description">
+ <span v-show="tabDescription === 'input'">
+ <Field v-slot="{ errors }" v-model="space.description" name="description">
+ </span>
【次回】$axiosをFetch APIに書き換える
vee-validateのエラー表示は消えましたが、
今度は$axiosのエラーでクルクルが表示されたままになりました。
$axiosは廃止されたようなので、次回はFetch APIに書き換えます。少ない修正量を目指す。
→ Nuxt BridgeをNuxt3に移行。$axiosをFetch APIに書き換える
今回のコミット内容
origin#507 vee-validateを導入
origin#507 v-text-fieldで初期値が表示されない。v-file-inputがエラーになる。useApiRequestのFormData対応
“Nuxt BridgeをNuxt3に移行。vee-validateを導入” に対して1件のコメントがあります。