patorashのブログ

方向性はまだない

GETメソッドのFormでの画面遷移をTurbolinksに委ねる

今作ってるアプリケーションではTurbolinksを効かせてて、かなりいい感じだな〜と思ってるのですが、一覧で検索した結果や表示件数を変更した場合に、ページの更新が発生してサクサク移動してたのに、ここでもたつくなぁ…と課題に感じていました。

なんとなくググってみたところ、TurbolinksのTipsとしてissueに上げられていたのでこりゃいい!と思ったので、やり方を書いておきます。

元ネタはここです。

github.com

元ネタのほうだと、jQueryを使っていたりしたので依存度を下げたい。また、data-remote=trueを対象にしていたりして、なんかよくわかりません・・・。data-remote=trueはもともとAjaxで値を取得しにいくから、ダメじゃないの?って思うんですが…。画面の一部を書き換えるときとかならわかるのですが、全体を書き換えたいのを対象にするのであれば、上記の一番最初のサンプルコードのように、data-remote=falseを対象とするべきでしょう。しかし、form_withヘルパーメソッドでlocal=trueにした場合、data-remote=falseという属性は出力されていないので、data-remote=trueを除外する、というアプローチをとります。

コードを紹介

gistを作っておいたのでそちらを見てみましょう。

Support GET from with Turbolinks.

解説

やっていることは以下の通り。

  1. turbolinks:loadイベントで、Turbolinksに委ねてもいいフォームを抽出する
  2. フォームのsubmitイベントを拾うよう設定する
  3. 本来のsubmitイベントをキャンセルする
  4. 現在のページと遷移先にページが同じ場合、perパラメータを引き継ぐ(kaminariの表示件数)
  5. フォームに入力されたものをクエリ文字列に変換する
  6. Turbolinks.visitで移動する

これの肝はクエリセレクタでうまいこと対象のフォームだけを抽出することです。

document.querySelectorAll('form[method=get]:not([data-remote=true])')で、GETメソッドだけどdata-remote=trueのものは除外しています。

また、ページングのgemであるkaminariを使っているので、表示件数をコントロールできるようにするため、pathnameに変更がない場合はperパラメータは引き継ぐようにしました。

まとめ

これで、検索フォームも超速くなりました🚀