2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Laravel10 + Vue3 + Inertia + PrecognitionでフォームリクエストのバリデーションをVueで使う

Posted at

はじめに

この記事ではPrecognitionというツールを使ってInertia + Vueのバリデーションを実装する方法について書いています。
PrecognitionはLaravelのフォームリクエストで定義したバリデーションを使用して、Vue等のフロントエンドでも使用するためのライブラリです。つまりバリデーションをLaravel側に統一することができます。

前提

  • Laravel + Vue + Inertiaで環境構築ができている
  • サンプルコードには<script setup>構文を使う

Precognitionを導入・設定

以下の順に作業を行っていきます。

  1. フォームリクエストを作成
  2. コントローラーを作成
  3. Precognitionをインストール
  4. ルーティングを設定
  5. Vueファイルを作成

Precognitionの導入方法だけを確認したい方は3.から見ていただければと思います。
それでは説明してきます。

フォームリクエストを作成

まずはフォームリクエストのファイルを作成します。

app/Http/Requests/UserRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class UserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required|max:255',
            'email' => 'required',
        ];
    }
}

このようにフォームリクエストは普通にバリデーションを定義するだけで、Vue側にエラーメッセージを表示することができます。

コントローラーを作成

次にコントローラーを作成します。

app/Http/Controllers/UserController.php
<?php

namespace App\Http\Controllers;

use App\Http\Requests\UserRequest;
use Inertia\Inertia;

class UserController extends Controller
{
    public function index()
    {
        return Inertia::render('users/index');
    }

    public function store(UserRequest $request)
    {
        return Inertia::render('users/index');
    }
}

今回はバリデーションが実装できているかどうかのみを確認するため、$requestは使いません。

Precognitionをインストール

ライブラリのインストールを行います。

$ npm install laravel-precognition-vue-inertia

上記はInertia + Vue用のライブラリをインストールするためのコマンドになります。

ルーティングを設定

ルートに対してPrecognitionを適用する必要があります。
下記のようにルートを定義します。

routes/web.php
<?php

use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;

// 略

Route::get('/users', [UserController::class, 'index']);
Route::post('/users', [UserController::class, 'store'])->middleware([HandlePrecognitiveRequests::class]);

ミドルウェアとして設定しているHandlePrecognitiveRequests::classPrecognitionを適用することができます。

Vueファイルを作成

最後にVueファイルを作成します。

resources/js/Pages/users/index.vue
<script setup>
import { useForm } from "laravel-precognition-vue-inertia"

const form = useForm("post", "/users", {
    name: "",
    email: ""
})

const submit = () =>
    form.submit({
        // trueにしておくとリダイレクトされた際にフォームの場所までスクロールしてくれる
        preserveScroll: true, 
        // リクエスト成功時にフォームに入力された内容をリセットする
        onSuccess: () => form.reset()
    })
</script>

<template>
    <form @submit.prevent="submit">
        <div>
            <label for="name">名前</label>
            <input id="name" v-model="form.name" />
            <div v-if="form.invalid('name')" class="error-message">
                {{ form.errors.name }}
            </div>
        </div>
        <div>
            <label for="email">メールアドレス</label>
            <input
                id="email"
                type="email"
                v-model="form.email"
                @change="form.validate('email')"
            />
            <div v-if="form.invalid('email')" class="error-message">
                {{ form.errors.email }}
            </div>
        </div>
        <button :disabled="form.processing">Create User</button>
    </form>
</template>

<style scoped>
form {
    padding: 10px;
}
label {
    display: block;
}
button {
    margin-top: 10px;
}
.error-message {
    color: red;
}
</style>

フォームに何も入力せずに作成ボタンを押すと下記のようにエラーメッセージが表示されます。
Precognition-1.png

また、名前フォームに256以上入力して作成ボタンを押すと、文字数超過のメッセージが表示されます。
Precognition-2.png

これでフォームリクエストのバリデーションが適用されていることがわかりました。

補足

リクエストを送信した際に特定のタイミングで何かしらの処理走らせることができます。

resources/js/Pages/users/index.vue
<script setup>

// 略
const submit = () =>
    form.submit({
        onBefore: (visit) => console.log("before", visit), // リクエスト前
        onStart: (visit) => console.log("start", visit), // リクエスト開始時
        onError: (errors) => console.log("error", errors), // バリデーションエラー発生時
        onFinish: (visit) => console.log("finish", visit), // リクエスト処理の終了時
        onSuccess: (page) => console.log("success", page), // リクエスト成功時
    })
</script>
// 略

onFinishはリクエストが成功しても失敗しても実行されます。また、各アロー関数の引数で定義しているvisiterrorsなどはフォームの入力値やエラーメッセージ等が格納されています。気になる方は実際に確認してみてください。

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?