本年6月から、マイホムにジョインしましたkokoeです。わっしょい。
そして、こちらは株式会社マイホム Advent Calendar 2021 6日目の記事です♪(あれっ。。間があいてる)
最近、VeeValidateを使ってフォームバリデーションを実装していたのですが、
ラジオ・チェック・セレクトボックスのバリデーションにつまづいたもんで、解決した方法をメモがてら書きのこしていきたいと思います。
前提
以下のバージョンで確認しています。
- VeeValidate v3
- Vue.js v2
ラジオボックス・チェックボックスの必須バリデーションができない!
required allowFalse=false
を指定します。
https://vee-validate.logaretm.com/v3/guide/rules.html#required
<ValidationProvider
vid="foo-checkbox"
:rules="{ required: { allowFalse: false } }"
>
<input type="checkbox" v-model="foo" />
</ValidationProvider>
セレクトボックスの必須バリデーションができない!
必須=デフォルト値以外、という意図で使っています。
デフォルト値が空のケース
skip-if-empty=false
を指定します。
https://vee-validate.logaretm.com/v3/api/validation-provider.html#props
<ValidationProvider
vid="foo-select"
rules="required"
:skip-if-empty="false"
>
<select v-model="selectValue">
<option value="">-- 選択 --</option>
<option value="foo">-- foo --</option>
<option value="bar">-- bar --</option>
</select>
</ValidationProvider>
デフォルト値が空以外のケース
カスタムルールをつくりましょう。
import { extend } from 'vee-validate';
import type { ValidationRule } from 'vee-validate/dist/types/types';
/**
* セレクトボックス required
* required_select:${defaultValue},${defaultValueType} を指定
*
* @example
* この例では、0がデフォルト値で、0をnumber型に変換した値でvalue値と比較する
* <ValidationProvider rules="required_select:0,number"></ValidationProvider>
*/
const required_select: ValidationRule = {
validate(
value: unknown,
params: [unknown, 'string' | 'number' | 'boolean']
) {
// params[0]:デフォルト値。valueがデフォルト値なら invalid
const defaultValue = Array.isArray(params) ? params[0] : '';
// params[1]:デフォルト値の型指定(paramsはstring[]なので)
const dataType = Array.isArray(params) ? params[1] || 'string' : 'string';
const formattedDefaultValue = (() => {
switch (dataType) {
case 'number':
return Number(defaultValue);
case 'boolean':
return Boolean(defaultValue);
default:
return defaultValue;
}
})();
return value !== formattedDefaultValue;
},
message: '{_field_}を選択してください'
};
extend('required_select', required_select);
valueを文字列で扱う
<ValidationProvider
v-slot="{ errors }"
vid="foo"
name="foo select"
rules="required_select:none,string"
>
<select v-model="selectValue">
<option value="none">-- 選択 --</option>
<option value="foo">-- foo --</option>
<option value="bar">-- bar --</option>
</select>
<p>{{ errors[0] }}</p>
</ValidationProvider>
valueを数値で扱う
<ValidationProvider
v-slot="{ errors }"
vid="foo"
name="foo select"
rules="required_select:0,number"
>
<select v-model.number="selectValue">
<option value="0">-- 選択 --</option>
<option value="1">-- foo --</option>
<option value="2">-- bar --</option>
</select>
<p>{{ errors[0] }}</p>
</ValidationProvider>
おわり
使い方覚えると、かなりのバリデーションパターンに対応できてほんとに便利です。
また、次のアドベントカレンダーネタもVeeValidateでいこうかな。
ご覧いただきありがとうございました。ぺこり。