Hello,
I’m looking for advice on structuring turbo frames and a form so that I can filter some results, and store the state in the query string, without affecting the path of the current page.
We have a couple of routes and turbo frames for a result filtering style experience:
-
/index
- a lightweight ‘shell’ that loads very quickly without any expensive fetches, SPA-style. - The index page contains a
filters
turbo frame with a form for filtering, and aresults
frame with asrc
of/results
. Results are computationally expensive, hence the separate frame and route to keep the initial page load fast.
Interacting with the filter form sets the src
of the results
frame, to trigger fetching results.
<turbo-frame id="filters">
<form action="/results" data-turbo-action="advance" data-turbo-frame="results" method="get">
<!-- form contents -->
</form>
</turbo-frame>
<turbo-frame id="results" src="/results">
<!-- results -->
</turbo-frame>
This is nice as the query string is updated when the user interacts with the filtering form, thanks to the data-turbo-action="advance"
, but the issue is that it sets the whole path to /results?x=y
, as that is the target of the form, whereas I’d like to always keep the user on /index?x=y
.
I’d like a solution that:
- Always keeps the URL consistently
/index
, never changes it to/results
- Keeps the query string / history in the browser in sync with the users interactions with the form
- Triggers fetching the new results when the user interacts with the filtering form.
- Ideally I don’t have to re-render the
filters
frame, as it has some UI state like opening dropdowns that should be persisted as the user interacts with the form.
The only option I can think of is not setting turbo-action
on the form, and using some JS in a stimulus controller to push a navigation event and update the query string, but I’m hoping there’s a more idiomatic turbo way of achieving this?
I’m open to restructuring the turbo frames completely if there’s a better way.