Home > Software design >  Turbo Stream link_to strips out custom attributes in GET request
Turbo Stream link_to strips out custom attributes in GET request

Time:01-25

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.

CodePudding user response:

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

https://github.com/hotwired/turbo/pull/821

  • Related