【laravel】ajaxを使用してバリデーションする方法(初心者向け)

laravelでフォームを作っていて、入力後にバリデーションをかけたい場面に出会ったことがあると思います。
ボタンを押してから入力チェックをしてエラーにする流れだと、場面によってユーザーにとって少しストレスになることもあります。

特に、

  • 入力値が変わったタイミングで、その場でチェックしたい
  • バリデーションのたびに画面を再読み込みしたくない
  • 入力ミスなら、もっと早い段階で教えてほしい

こういった要望もよくあると思います。

そこで今回は、laravelとajax(jQuery)を使用して非同期でバリデーションを行う方法を紹介します。

画面遷移をせずにエラーチェックを行い、入力値が変わった時にその場でエラーメッセージを表示することで、
ユーザーにとって使いやすいフォームを実装していきます。

laravel標準のバリデーションをそのまま活かした構成なので、特別難しいことはせず、すぐに取り入れられます。

  • 入力後、その場でエラーを表示できる
  • 画面遷移なしでバリデーションでき、ストレスのないフォームになる
  • ユーザーが入力ミスにすぐ気づけるため、離脱を防げる
  • laravelでのajaxバリデーションの基本構成が理解できる
目次

実装

実装する流れ

  • フォームを作成し、値が変わった時にajaxを使用してバリデーション用のメソッドにPOSTする
  • controller側で標準のバリデーションを実装する
  • エラーのときにはエラーの内容をJSON形式で返す
  • 返ってきたメッセージをjs側で表示させる

フォームの作成とonchange

今回の画面イメージは以下とします。

それぞれinputタグを使用してidプロパティを付与しています。

		//~~~~省略~~~~
		<form id="form">
			@csrf
			<div class="validate">
				名前:<input type="text" id="name" name="name" value="山田太郎">
			</div>
			<div class="validate">
				年齢:<input type="text" id="age" name="age" value="23">
			</div>
			<br>
			<button type="submit">POST送信</button>
		</form>
		//~~~~省略~~~~

headタグ内に以下のscriptを書き、idを指定して特定の要素の入力値が変わった時にイベントを発火させるようにします。
その後、ajaxを利用して「/ajax_validate」のルートへ飛ばします。

    <script>
				$(function(){
				  //名前と年齢に対して入力値が変わった時にイベントを発火
					$("#name, #age").on("change", function(){
						checkValidate();
					});
				});
				
				//バリデーションメソッドにPOST
				function checkValidate(){
					$.ajaxSetup({
						headers: {
							'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
						}
					});

					$.ajax({
						type: "POST",
						url: "/ajax_validate",
						data: {
							name: $("#name").val(),
							age: $("#age").val(),
						},
						dataType : "json",
					})
					.done(function(response){
						console.log(response);
					});
				}
    </script>

ルートの設定も忘れないようにしましょう。
web.phpに以下を追記します。

//~~~省略~~~
Route::post('/ajax_validate', [AjaxValidateController::class, 'checkValidate'])->name('postAjaxValidate');
//~~~省略~~~

補足

onchangeを選択したのは、

  • 入力途中でエラーを出したくない
  • 不要な通信を避けたい

が主な理由です。
入力されるたびにイベントが走ると何度も通信が走り、さらにエラーメッセージが何度も表示されることになるため入力後にイベントが走るようにします。

値が変わっていなくても、フォーカスが外れたときに発火する「onblur」も使用できますので、ケースに合わせて使用しましょう。

laravel標準バリデーションを実装

エラーがあったかどうかを判定する「fails」を使用し、エラーとなった場合はその内容をJSON形式に変換して返します。

//~~~省略~~~
    public function checkValidate()
    {
        //エラーチェック
		    $validator = Validator::make(request()->all(),[
			    'name' => ['required'],
			    'age' => ['required'],
		    ]);

        if ($validator->fails()) {
            return response()->json([
                'errors' => $validator->errors()->toArray(),
            ]);
        }
    }
//~~~省略~~~

jsでエラーメッセージを表示

返ってきた情報をもとにエラーメッセージを表示します。
値が変更されるたびにバリデーションが走るため、最初はエラーメッセージをリセットします。

「key」の中にはエラーとなったname属性が入るため、そのキーを参照して、同じid属性かつ、その親要素である「validate」クラスが付いたdivタグの最後にエラーメッセージを表示します。

function checkValidate(){
					$.ajaxSetup({
						headers: {
							'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
						}
					});

					$.ajax({
						type: "POST",
						url: "/ajax_validate",
						data: {
							name: $("#name").val(),
							age: $("#age").val(),
						},
						dataType : "json",
					})
					.done(function(response){
					  //↓追記↓
						let errorList = response.errors;

						//エラーメッセージリセット
						$(".error-message").remove();

						//エラーとなったキーを参照して同じidの直下に表示する
						for (key in errorList) {
							let message = errorList[key];
							let id = $("[name='"+key+"']").attr("id");

							$("#" + id).closest(".validate").append(
								"<div class='error-message'>" + message + "</div>"
							)
						}
						//↑追記↑
					});
				}

まとめ

今回は、laravelとajaxのonchangeイベントを使って、非同期でバリデーションを実装する方法を紹介しました。
フォームの入力項目を変更したタイミングでサーバー側にリクエストを送信し、エラーがある場合は 画面遷移せずにその場でフィードバックすることで、ユーザーに優しいものになります。

こうした実装は最初は少しハードルが高く感じるかもしれませんが、一度仕組みを理解してしまえば、様々な場面で応用できます。

  • URLをコピーしました!
目次