Vue.jsを使ったWebアプリ開発では、ユーザーが任意の数の入力項目を追加・削除できる「動的フォーム」がよく登場します。代表例として、複数の連絡先や参加者情報を入力するフォーム、項目単位でデータを登録する明細入力などが挙げられます。
本記事では、Vue.jsで動的フォームを構築する方法と、各入力フィールドに対してバリデーションを適用する設計パターンを紹介します。
v-forを使った動的なフォーム項目のレンダリング
フォームを動的に構築するには、配列で入力フィールドを管理し、v-for
で繰り返し描画します。以下は名前フィールドを複数追加できるシンプルな例です。
<template> <div> <div v-for="(field, index) in fields" :key="index"> <input v-model="field.name" placeholder="名前を入力" /> <button @click="removeField(index)">削除</button> </div> <button @click="addField">項目を追加</button> </div> </template> <script> export default { data() { return { fields: [{ name: '' }] }; }, methods: { addField() { this.fields.push({ name: '' }); }, removeField(index) { this.fields.splice(index, 1); } } } </script>
このように、配列fields
の操作に応じて入力フィールドを追加・削除できる構造が実現できます。
簡易なバリデーションの実装
必須入力チェックなど、基本的なバリデーションはcomputed
プロパティやメソッドを活用して実装できます。
computed: { hasEmptyField() { return this.fields.some(field => field.name.trim() === ''); } }
hasEmptyField
がtrue
なら「すべて入力してください」といった警告を表示し、送信ボタンを無効化できます。
<div v-if="hasEmptyField" class="error">すべての項目に入力してください。</div> <button :disabled="hasEmptyField">送信</button>
VeeValidateを使った高度なバリデーション
より高度なチェックや再利用性を求めるなら、VeeValidateなどの外部バリデーションライブラリが有効です。VeeValidate v4ではYupと連携してスキーマベースのチェックが可能です。
import { useForm, useFieldArray } from 'vee-validate'; import * as yup from 'yup'; const schema = yup.object({ fields: yup.array().of( yup.object({ name: yup.string().required('名前は必須です') }) ) }); const { handleSubmit, errors, values } = useForm({ validationSchema: schema }); const { fields, remove, push } = useFieldArray('fields');
このように、バリデーションロジックとフォーム構造を分離しつつ、柔軟に制御することが可能です。
実用シーンと拡張例
動的フォームは以下のような場面で活用されます。
- 明細付き請求フォーム(項目+金額+数量)
- 複数ファイル名やURLの登録欄
- FAQなど質問+回答セットの入力画面
さらに、ネストされた配列(フォーム内にさらに動的項目がある)やリアルタイムでの合計値計算なども応用できます。
まとめ
Vue.jsでは、配列とv-for
の組み合わせによって柔軟な動的フォームの構築が可能です。バリデーションも、シンプルなcomputedチェックから、VeeValidateを用いたスキーマベースの管理まで対応できます。
ユーザー入力の自由度と安全性の両立が求められる場面で、ぜひ今回の実装パターンを取り入れてみてください。