Vueでバリデーションというと、まず挙がるのはVeeValidateかと思います。
ある仕事でNuxt.jsを使う現場にアサインされた時も、バリデーターはVeeValidateが採用されてました。
でもあれ、記述が重いんですよね…。
どっちにしろバックエンドでバリデーションしますし。
趣味のサイトで、あそこまで高機能じゃなくていいからもうちょい楽にバリデーションできないかなぁと考えて思い出したのがHTML5標準のフォームバリデータ。
挙動はブラウザ依存にはなってしまいますが、例えばrequired
タグを付けるだけで、IE以外はバルーン表示でユーザに告知してくれます。必要十分で、楽です。
素のJavaScriptによるHTML5フォームバリデータ例
MDNでは「JavaScript無しの素のHTMLフォームでもバリデーション可能です」という紹介のされ方ですが、JavaScriptからDOM操作で該当のイベントを起動することが出来ます。
See the Pen HTML5 フォームバリデーション 素JavaScript実装例 by belgh (@belgh) on CodePen.
チェックボタンを押すと、HTMLのinputタグの属性に従ってバリデーションが行われるのが確認できると思います。
(本サンプルでは、:valid、:invalidで自動適用されるclassも設定しています)
JavaScript側ではイベント起動してるだけで、他は何もしていません。
上記のチェック例はrequired
minlength="10"
です。
他にemailやtel、dateなどのinput type
によるバリデーションや、pattern
属性で正規表現を使うことも出来ます。
また、後述する方法で独自のバリデーションを実装することも出来ます。
(あまり複雑になるようだと、モジュール使ったほうがいいような気もしますが…)
Vue3(TypeScript)での実装例
ポイントはref
を使うこと。
TypeScriptの場合はHTMLInputElement型を明示します。
それだけです。
<script setup lang="ts">
import { ref } from 'vue'
// props略
const form = ref<HTMLInputElement | null>(null)
const validate = () => {
if (form.value?.checkValidity() == false) {
form.value.reportValidity()
return false
}
return true
}
const create = () => {
if (!validate()) {
return false
}
// 以下略
}
</script>
<template>
<form ref="form">
<input :model="params.name" type="text" required minlength="10">
<button type="button" @click="create">
登録
</button>
</form>
</template>
- 参考
https://ja.vuejs.org/guide/essentials/template-refs.html#accessing-the-refs
https://reffect.co.jp/vue/vue3-composition
エラーの表現方法はバルーンで固定されてしまいますが、
- template部分のルール記載がものすごくシンプル
- バリデーションのトリガイベントを書くだけで、実際のバリデーションとエラー告知はブラウザ任せ
であることが利点です。
楽でいいですよね。
独自のバリデーションを実装する
これに手を出すくらいなら有り物のモジュールに乗っかったほうがいいのでは…?
という意味であまり使う機会はないかもしれませんが、
独自のバリデーション実装も可能です。
以下は、標準では行えない「添付ファイルのサイズ」をチェックする例です。
<script>
const catchFile = (e: Event) => {
if (e.target instanceof HTMLInputElement) {
// checkValidityはエラーメッセージの有無に依存するので、必ずクリアする
e.target.setCustomValidity('')
if (e.target.files) {
const image = e.target.files.item(0);
if (image.size > 1024 * 1024 * 5) {
// エラーメッセージを設定すると、checkValidityがfalseになる
e.target.setCustomValidity(
'ファイルサイズは5MB以下にしてください。'
)
}
}
}
}
</script>
<template>
<input @change="catchFile" type="file" required>
</template>
これくらいなら許容範囲かな?と思います。
おわり。