带有 data-turbo 的 Rails 'link_to' 不会获得TURBO_STREAM请求格式

Rails `link_to` with data-turbo doesnt get TURBO_STREAM request format

提问人:nimmolo 提问时间:11/6/2023 最后编辑:nimmolo 更新时间:11/7/2023 访问量:123

问:

(原始问题:是否禁用链接中的涡轮请求?不,即使有Turbo.setFormMode("optin")Turbo.setFormMode("on"))

使用 Rails 6.1 的成熟应用程序,最近添加了 gem 1.5.0、gem 1.2.3 以开始将表单转换为 Hotwire。turbo-railsimportmap-rails

# app/javascript/application.js
import "@hotwired/turbo-rails"
Turbo.setFormMode("optin")

在翻译页面模板中,我有这样的链接,这些链接应该得到一个小型编辑表单的涡轮流请求。响应应该在页面的其他地方更新一个单独的涡轮框架(或 div,两者都尝试过),将其替换为编辑表单。erb

问题是这些链接没有发送,它们正在发送。链接是使用如下所示的帮助程序构建的:request.format turbo-streamrequest.format text/html

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" })

控制器操作,没什么疯狂的,多年来一直与UJS合作:

  def edit
    @lang = set_language_and_authorize_user
    @tag = params[:id]
  rescue StandardError => e
    @msg = error_message(e).join("\n")
  end

响应模板:

# app/views/translations/edit.erb

<%= turbo_stream.replace("translation_ui") do
  render(partial: "translations/form", layout: false)
  render(partial: "translations/versions", layout: false)
end %>

如果我在浏览器中测试页面,正在加载turbojs,没有js错误,HTML已正确构建。请注意,“索引”包含用于更新右侧单独涡轮框架的链接,编辑表单应在其中加载。它不需要是涡轮增压框架——我已经尝试过将其作为带有 id 的 div。

<!-- 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>

但是单击该链接不会向控制器发送 GET,request.format 为 或 。这是我在控制台中得到的:request.format == turbo_streamtext/html*/*

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 链接可在应用程序的其他位置使用。为什么会这样?

请注意,我知道在元素的任何祖先上设置都会为所有子元素禁用 Turbo,但这里的情况并非如此。Turbo.setFormMode = optindata-turbo=false

我尝试过的事情:

  • 根据此 SO Q/A 修改链路路径edit_translation_path(format: "turbo-stream")
  • 根据此 SO Q/A 修改路由get(:edit, to: "translations#edit", as: "edit_translation", defaults: { format: :turbo_stream })
  • 添加到 ,根据此问题Turbo.session.drive = trueapp/javascript/application.js
  • link_to(data: { turbo_method: :get }根据这个答案
  • Turbo.setFormMode("on")app/javascript/application.js

跆拳道!这些都不会对从链接发送的 request.format 产生任何影响。

Ruby-on-Rails 涡轮增压 导轨

评论

0赞 zaphodbln_ 11/6/2023
也许你可以庆祝你所期待的。至少对我来说,这还不是那么清楚。据我所知,您必须决定更改是从服务器(这就是您使用 turbo_stream 的原因)还是从客户端(因为您选择加入 turbo)发起的。我猜你想回应点击 - 在这里你不需要涡轮流。将您的表单或部分封装到涡轮框架中,并确保在您的响应中包含涡轮框架定义 - 请参阅此处:turbo.hotwired.dev/handbook/frames
0赞 zaphodbln_ 11/6/2023
也许你可以分享你的部分
0赞 nimmolo 11/7/2023
谢谢@zaphodbln_。我已经更新以显示更多的“索引”模板,并且响应部分存在于答案中 - 要更新的框架或 div 与原始链接是分开的。更深层次的问题是点击不是作为 turbo 请求发送的——我确信这一点,因为当我在 Ruby 控制台中 Rails 控制器的操作期间中断并检查时,它是“text/html”。换句话说,问题似乎不是控制器无法找出正确的涡轮增压响应,而是请求是错误的。editeditrequest.format

答:

1赞 Alex 11/7/2023 #1

data-turbo-stream指定链接或表单可以接受 Turbo Streams 响应。Turbo 自动请求使用非方法提交表单的流响应;
允许 Turbo Streams 也用于请求。
GETdata-turbo-streamGET

https://turbo.hotwired.dev/reference/attributes

GET 链接和 GET 表单需要具有属性才能发送TURBO_STREAM请求:data-turbo-stream

<%= link_to "GET link", "/", data: {turbo_stream: true} %>

<%= form_with url: "/", method: :get, data: {turbo_stream: true} do |f| %>
  <%= f.submit "GET form" %>
<% end %>

您还必须为表单指定:Turbo.setFormMode("optin")data-turbo="true"

<%= form_with url: "/", method: :get,
  data: {
    turbo: true,
    turbo_stream: true
  } do |f| %>

  <%= f.submit "GET form" %>
<% end %>

评论

0赞 nimmolo 11/7/2023
谢谢@Alex - 天哪,就是这样!是否确定不会在 GET 链接上设置请求格式?或者,如果链接不是来自涡轮增压框架本身,则不是?还想为其他人注意,我必须删除路径帮助参数,以及我为此投入的所有其他内容以使其工作。吉布斯难倒了我几个小时。data-turbo-frameformat: :turbo_stream
1赞 Alex 11/7/2023
指定不会改变它保持为 HTML 的格式,它唯一做的就是设置一个带有帧名称的标题(默认情况下,它仅用于跳过渲染 Turbo 帧请求的布局)。但是,从技术上讲,您可以将turbo_stream呈现为对 Turbo 帧请求的响应。data-turbo-frameTurbo-Frame
0赞 nimmolo 11/7/2023
谢谢。我注意到,如果我在链接上同时设置了两者,将页面元素和我的响应模板都更改为 ,则不会更新。所以我用 divs 和 .行得通!data: { turbo_stream: true, turbo_frame: "translation_ui" })turbo_frame_tagturbo_stream:update