Inertiaにおけるフォームの実装方法
次に、図1のカクテル追加画面での処理について説明します。
データ追加のアクションメソッドは従来通り
図1のカクテル追加画面での[追加]ボタンをクリックした際のパスを/addCocktail、その際に呼び出されるアクションメソッドをaddCocktail()とした場合、そのコードはリスト3のようになります。
class CocktailController extends Controller { : public function addCocktail(Request $request) { $request->validate([ // (1) "cocktailName" => "required", // (1) "cocktailPrice" => "required|gte:100" // (1) ]); // (1) $cocktail = new Cocktail(); // (2) $cocktail->name = $request->cocktailName; // (2) $cocktail->price = $request->cocktailPrice; // (2) $cocktail->save(); // (2) return redirect("/cocktailList"); // (3) } }
リスト3のコードを見るとわかるように、Inertiaを利用していても、データ処理コードは、Bladeを利用した場合と全く同じものとなります。
(1)では入力データのバリデーションを行っています。カクテル名のリクエストパラメータであるcocktailNameには必須チェックを、同じくカクテルの金額であるcocktailPriceに必須チェックと最小値チェックを行っています。これらは、第2回で紹介したものと同じバリデーションです。
その後(2)でデータベースへの保存処理を行い、(3)でカクテルリスト画面にリダイレクトしています。
フォーム用のFormコンポーネント
一方、画面そのものであるコンポーネントのコードは、当然Bladeとは違い、リスト4のようになります。
<script setup lang="ts"> import {Link, Form} from "@inertiajs/vue3"; interface Props { // (1) errors: { // (2) cocktailName?: string; // (3) cocktailPrice?: string; // (4) } } defineProps<Props>(); </script> <template> <h1>カクテル管理</h1> <section> <h2>カクテル追加</h2> <Form action="/addCocktail" method="post"> // (5) <label for="cocktailName">カクテル名</label> // (6) <input type="text" name="cocktailName" id="cocktailName"> // (6) <div v-if="errors.cocktailName">{{ errors.cocktailName }}</div><br> // (7) <label for="cocktailPrice">金額</label> // (8) <input type="number" name="cocktailPrice" id="cocktailPrice"> // (8) <div v-if="errors.cocktailPrice">{{ errors.cocktailPrice }}</div><br> // (9) <button type="submit">追加</button> </Form> <Link href="/cocktailList">カクテルリストへ戻る</Link> </section> </template>
リスト4の(6)と(8)に注目すると、通常のフォームの記述と同じであることがわかります。(6)がカクテル名(リクエストパラメータcocktailName)の入力欄、(8)がカクテルの金額(リクエストパラメータcocktailPrice)の入力欄です。
通常のフォーム記述と違うのは、これらの入力コントロールタグがformタグではなく、(5)のように大文字で始まるFormタグに囲まれている点です。このFormタグは、Inertiaによって用意されたFormコンポーネントであり、Linkコンポーネント同様に、この画面が表示される際、およびリダイレクトなどで別の画面へ遷移する際も、全画面を再レンダリングするのではなく、シングルページアプリケーションのように必要な部分のみレンダリングされるようになります。
バリデーションメッセージはPropsを利用
さらに、Formコンポーネントを利用することで、サーバサイドバリデーション、すなわち、アクションメソッドにおけるバリデーション(リスト3ならば(1))の結果を効率よく扱えるようになります。それが、リスト4の(7)と(9)です。
まず、サーバサイドでバリデーションが行われ、その結果、入力画面が再表示される場合、バリデーションメッセージはPropsとして渡されます。そのため、リスト4の(1)のようにPropsインターフェースを定義し、その中に(2)のerrorsプロパティを定義します。
プロパティ値はオブジェクトです。そのerrorオブジェクト内には、リクエストパラメータ名をプロパティ名、文字列を値とするプロパティを定義していきます。(3)がリクエストパラメータcocktailNameであるカクテル名のバリデーションメッセージ、(4)がリクエストパラメータcocktailPriceであるカクテルの金額のバリデーションメッセージが格納されるプロパティです。ただし、これらのバリデーションメッセージは、入力値が適切な場合は存在しません。そのため、?を記述してオプション扱いとします。
このようにしてPropsとして渡されるバリデーションメッセージを表示しているのが、(7)と(9)です。(7)がカクテル名に関するバリデーションメッセージ、(9)がカクテルの金額に関するバリデーションメッセージです。ただし、バリデーションメッセージはオプション扱いなので、v-ifを利用して、メッセージがある場合のみ表示させるようにしています。