I'm using Rails 7. I wanted to create a link using link_to that inserts some custom form fields for a many-to-many relation into a form via a hotwired frame elsewhere on the page. In order to customize the form fields generated (setting defaults etc) I need to include some custom parameters in the request:
<%= link_to "Add crew to ship",
new_crew_path(ship_id: ship.id),
data: { turbo_method: :get,
turbo_stream: true } %>
The HTML looks correct, but when clicking the link, the parameter seems to have been stripped away:
<a data-turbo-method="get" data-turbo-stream="true" href="/crews/new?ship_id=1">Add crew to ship</a>
...
Started GET "/crews/new" for 127.0.0.1 at 2023-01-24 13:49:23 +0100
Processing by CrewsController#new as TURBO_STREAM
If I remove the data map defining turbo_stream: true
so it becomes a regular request, it works fine:
<%= link_to "Add crew to ship",
new_crew_path(ship_id: ship.id) %>
Started GET "/crews/new?ship_id=1" for 127.0.0.1 at 2023-01-24 13:53:26 +0100
Processing by CrewsController#new as HTML
Incoming parameters: {"ship_id"=>"1"}
Same for changing it to a POST request, so it goes to the #create action of the controller instead, that also works:
<%= link_to "Add crew to ship",
crews_path(ship_id: ship.id),
data: { turbo_method: :post,
turbo_stream: true } %>
Started POST "/crews?ship_id=1" for 127.0.0.1 at 2023-01-24 13:58:01 +0100
Processing by CrewsController#create as TURBO_STREAM
Incoming parameters: {"ship_id"=>"1"}
So I have workarounds. Nevertheless, out of curiousity, is there some way to make GET turbo requests submit the custom params? From a REST perspective it feels like the most correct request method.
When you add turbo_method: :get
the link is treated as a form and GET forms overwrite url query params with form params. As a test:
// app/javascript/application.js
document.addEventListener("turbo:before-fetch-request", (event) => {
console.log(event.target)
})
// you get this "fake" form in the console, that Turbo submits instead of a link:
// <form data-turbo="true" action="http://localhost:3000/?ship_id=1" hidden="" method="get" data-turbo-stream=""></form>
If you just change the link to this:
<%= link_to "Add crew to ship",
new_crew_path(ship_id: ship.id),
data: { turbo_stream: true } %>
Now it's a regular GET turbo stream link, and query params should stay untouched.
For some extra details:
https://github.com/hotwired/turbo/pull/647
it's worth emphasizing that declaring
[data-turbo-method="get"]
on an<a>
element is redundant, and should be avoided