Rails and Turbo Frames: How to Use data-turbo-action to Preserve Search State

Let鈥檚 imagine an app with a search page. This page displays some content unrelated to search and includes a form for users to search within the app.

To avoid reloading the whole page, we decided to wrap the search form in a Turbo Frame:

<div> SOME CONTENT UNRELATED TO SEARCH </div>

<h1>Search</h1>

<%= turbo_frame_tag 'search' do %>
<%= form_with model: false, url: search_path, method: :get do |f| %>
<%= f.text_field :query, value: params[:query], placeholder: 'Search...' %> <%= f.submit "Search" %>
<% end %>

<%= render 'results', results: @results %>
<% end %>

If we visit mydomain.com/search, we’ll see something like this:

Search form

If we then fill in the form and submit it, we鈥檒l see the results under the form:

Results

馃殌 The advantage of using a turbo frame is that only the portion inside the turbo frame updates, making the response faster than a full-page reload.

The problem

The downside is that the URL remains mydomain.com/search, even after searching. If a user navigates away and then tries to return using the browser鈥檚 back button, the search results will be lost, requiring them to search again. A similar issue occurs if they try to share the search results by copying the URL.

Solution

To fix this, we can add data-turbo-action="advance" to the turbo frame. This ensures that submitting the form updates the URL to match the form action. In this case, the URL will change to: mydomain.com/search?query=something

<%= turbo_frame_tag "main", data: { turbo_action: "advance" } do %>
...
<% end %>