前回のTurbolinks、再びにおいて掲載した記事に、修正が必要なことに気づきました。登録フォームのPOSTでバリデーションエラーが出て同画面に戻るときは問題ないのですが、エラーがなく登録完了してホーム画面へリダイレクトされたときが問題です。
以下のように、画面はホーム画面の中身となっていますが、ブラウザのURLがhomeであるべきところ、registerのままでした。
これを修正するには、まずブレードのインラインのjsから、
... @section('script') $(document).on('turbolinks:load', function() { $("form").on("submit", function(event) { event.preventDefault(); $.ajax({ url: '/register', type: 'POST', dataType: 'html', processData: false, contentType: false, cache: false, data: new FormData($("form")[0]) }).done(function(response, status, $xhr) { var redirect = $xhr.getResponseHeader('Turbolinks-Location'); if (redirect) { // 投稿成功でリダイレクトしたとき Turbolinks.visit(redirect); } else { // バリデーションエラーのとき var referrer = window.location.href; Turbolinks.controller.cache.put(referrer, Turbolinks.Snapshot.wrap(response)); Turbolinks.visit(referrer, { action: 'restore' }); } }); }); }); @endsection
変更は、投稿で成功したときを認識して、Turbolinks.visit()
をリダイレクト先でコールするところです。
さて、問題は投稿が成功したか否かをどう判定するか、です。
それには、サーバーサイドでPOSTが生成するレスポンスのヘッダーにリダイレクト先を含む項目を追加してクライアント(ブラウザ)にコミュニケートする必要があります。上の例では、ヘッダーにTurbolinks-Locationの項目に値があれば、リダイレクトが必要という条件文になりました。その情報がなければ、バリデーションエラーが発生したので同じ画面を表示します。
さて、POSTのレスポンスにこの特別なヘッダーの情報を追加するには、以下のようにコントローラを編集します。
namespace App\Http\Controllers\Auth; use App\User; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Validator; use Illuminate\Foundation\Auth\RegistersUsers; // register()で使用される以下の2行の宣言が必要! use Illuminate\Http\Request; use Illuminate\Auth\Events\Registered; class RegisterController extends Controller { use RegistersUsers; ... /** * Handle a registration request for the application. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function register(Request $request) { $this->validator($request->all())->validate(); event(new Registered($user = $this->create($request->all()))); $this->guard()->login($user); // オリジナルのコード // return $this->registered($request, $user) // ?: redirect($this->redirectPath()); return response('success', 200) ->header('Turbolinks-Location', $this->redirectPath()); } }
RegistersUsers
のトレイトで定義されている、register()
メソッドをコピーペーストして上書きします。
ヘッダーのTurbolinks-Locationには、リダイレクト先のURLが含まれることになります。
ちなみに、response()
で指定している、’success’の文字列は使用しないのでなんでもよいです。空でも。
これで登録を実行すると、POSTのヘッダーには以下のように, Turbolinks-Locationは/homeの値となります。そして、その値が先のインラインのjsで抽出されて、Turbolinks.visit()
に渡されてbodyタグの中身を取り換えてブラウザのURLを変更します。
HTTP/1.1 200 OK Date: Fri, 13 Dec 2019 17:31:21 GMT Server: Apache/2.4.38 (Fedora) OpenSSL/1.1.1b X-Powered-By: PHP/7.2.16 Cache-Control: no-cache, private Turbolinks-Location: /home ...
リダイレクト先には、Turbolinks-Locationというヘッダーの変数名を使用しましたが、他と重複がなければどんな名前でもよいです。サーバーとクラインとで一致している限り。
コントローラを編集しなければならない部分が残念ですが、たいした編集ではないので、私の中ではやはりサイトのSPA化ではまだまだコストパフォーマンスが大きい技術です。
メルマガ購読の申し込みはこちらから。