(Original question: Does Turbo.setFormMode("optin")
disable turbo requests in links? No, the link doesn't work even with Turbo.setFormMode("on")
)
Mature app using Rails 6.1, recently added gem turbo-rails
1.5.0, gem importmap-rails
1.2.3 to start converting forms to Hotwire.
# app/javascript/application.js
import "@hotwired/turbo-rails"
Turbo.setFormMode("optin")
In a translation page erb
template, I have links like this that should GET a turbo-stream request for a tiny edit form. The response should update a separate turbo-frame (or a div, have tried both), elsewhere on the page, replacing it with the edit form.
The issue is that these links are not sending request.format turbo-stream
, they're sending request.format text/html
. The links are built with a helper like this:
link_to(label, edit_translation_path(id: t_tag, locale: @lang.locale),
data: { turbo: true, turbo_frame: "translation_ui",
tag: t_tag, role: "show_tag" })
Controller action, nothing crazy, has worked for years with UJS:
def edit
@lang = set_language_and_authorize_user
@tag = params[:id]
rescue StandardError => e
@msg = error_message(e).join("\n")
end
The response template:
# app/views/translations/edit.erb
<%= turbo_stream.replace("translation_ui") do
render(partial: "translations/form", layout: false)
render(partial: "translations/versions", layout: false)
end %>
If I test the page in the browser, turbojs is being loaded, there are no js errors, the HTML is correctly built. Note that the "index" contains links to update a separate turbo-frame on the right, where the edit form should load. It doesn't need to be a turbo-frame — I've tried this as a div with an id.
<!-- app/views/translations/index.erb produces this html -->
<div id="translation_index">
<a data-turbo="true" data-turbo-frame="translation_ui"
data-tag="hello" data-role="show_tag"
href="/translations/hello/edit?locale=en"><span class="tag">hello</span></a>
<a data-turbo="true" data-turbo-frame="translation_ui"
data-tag="hello" data-role="show_tag"
href="/translations/hello/edit?locale=en"><span class="tag"> goodbye</span></a>
</div>
<turbo-frame id="translation_ui"></turbo-frame>
But clicking the link does not send a GET request.format == turbo_stream
to the controller, the request.format is text/html
or */*
. This is what I get in the console:
Started GET "/translations/one/edit?locale=en" for ::1 at 2023-11-06 00:31:30 -0800
Processing by TranslationsController#edit as HTML
Parameters: {"locale"=>"en", "id"=>"one"}
Turbo links work elsewhere in the app. Why is this happening?
Note there is Turbo.setFormMode = optin
and I'm aware that setting data-turbo=false
on any ancestors of the element would disable Turbo for all children, but that is not the case here.
Things I have tried:
- modifying the link path
edit_translation_path(format: "turbo-stream")
per this SO Q/A - modifying the route
get(:edit, to: "translations#edit", as: "edit_translation", defaults: { format: :turbo_stream })
per this SO Q/A - adding
Turbo.session.drive = true
toapp/javascript/application.js
, per this issue link_to(data: { turbo_method: :get }
per this answerTurbo.setFormMode("on")
inapp/javascript/application.js
WTF! None of this has any effect on the request.format sent from the links.
https://turbo.hotwired.dev/reference/attributes
GET links and GET forms need to have
data-turbo-stream
attribute to send a TURBO_STREAM request:With
Turbo.setFormMode("optin")
you also have to specifydata-turbo="true"
for the form: