🙆

<turbo-frame>のみでインクリメンタル検索

2022/03/06に公開

やりたいこと

Turbo StreamsやJavaScriptの処理を書かずに、Turbo Framesのみでサーバーサイドで絞り込んだ検索結果をレンダリングしたい。

文字が入力される度に

サーバーで検索して画面に反映する

解決策

turbo.jsで定義されているrequestSubmit()をoninputイベントから呼び出してフォームをsubmitする。

  1. フォームからGET /notes?q=fooリクエストが発生
  2. レスポンスを<turbo-frame>でレンダリング
index.html.erb
<!--検索入力-->
<%= form_tag notes_path, method: :get, data: {turbo_frame: :notes} do %>
  <%= text_field_tag :q, params[:q], oninput: "requestSubmit()" %>
<% end %>

<!--検索結果表示欄-->
<%= turbo_frame_tag :notes, src: notes_path, loading: "lazy" %>
notes_controller.rb
class NotesController < ApplicationController
  def index
    @notes = params[:q] ? Note.where('title LIKE ?', "%#{params[:q]}%") : Note.all
  end
end
notes/index.html.erb
<!--検索結果-->
<%= turbo_frame_tag :notes do %>
  <% @notes.each do |note| %>
    <%= note.title %>
  <% end %>
<% end %>

補足

  • 結局JavaScriptで実行している
  • クライアントサイドに文字数制御などをロジックを追加するならStimulusで切り離した方が良さそう

Discussion