【问题标题】:Turbolinks to Turbo upgrade has broken form redirectionTurbolinks to Turbo 升级已破坏表单重定向
【发布时间】:2021-07-15 01:19:58
【问题描述】:

我正在尝试从 Turbolinks 升级到 Turbo,但我发现客户端没有为表单提交呈现重定向。

版本:

  • 导轨 6.1.4
  • hotwire-rails 0.1.2
  • @hotwired/turbo-rails 7.0.0-beta.8

我暂时忽略了 Turbo 和 Devise 之间的不兼容问题 - 只是试图让常规表单正常工作而不必禁用它们上的 Turbo。

这是一个示例操作:

def update
  authorize @label
  @label.update(label_params)
  if @label.save
    redirect_to document_labels_path(document_id: @document.id)
  else
    render :new, status: :unprocessable_entity
  end
end

这是一个渲染的表单:

<form class="simple_form new_label" id="label_form" novalidate="novalidate" action="/documents/72/labels" accept-charset="UTF-8" method="post">
...
</form>

当提交一个有效的表单时,服务器会说Processing by LabelsController#create as TURBO_STREAM 并正确地提供一个 302。然后它将为重定向位置提供 200。然而,浏览器只查看提交的表单。将重定向状态更改为 303 不会改变任何内容。

我为每个 Turbo 事件添加了一个 console.log:

document.addEventListener("turbo:load", function () {
  console.log('TURBO:LOAD')
})
document.addEventListener("turbo:click", function () {
  console.log('TURBO:CLICK')
})
document.addEventListener("turbo:before-visit", function () {
  console.log('TURBO:BEFORE-VISIT')
})
document.addEventListener("turbo:visit", function () {
  console.log('TURBO:VISIT')
})
document.addEventListener("turbo:submit-start", function () {
  console.log('TURBO:SUBMIT-START')
})
document.addEventListener("turbo:before-fetch-request", function () {
  console.log('TURBO:BEFORE-FETCH-REQUEST')
})
document.addEventListener("turbo:before-fetch-response", function () {
  console.log('TURBO:BEFORE-FETCH-RESPONSE')
})
document.addEventListener("turbo:submit-end", function (event) {
  console.log('TURBO:SUBMIT-END')
  // event.detail
})
document.addEventListener("turbo:before-cache", function () {
  console.log('TURBO:BEFORE-CACHE')
})
document.addEventListener("turbo:before-stream-render", function () {
  console.log('TURBO:BEFORE-STREAM-RENDER')
})
document.addEventListener("turbo:render", function () {
  console.log('TURBO:RENDER')
})

这是成功提交表单的输出:

TURBO:BEFORE-FETCH-REQUEST
TURBO:SUBMIT-START
TURBO:BEFORE-FETCH-RESPONSE
TURBO:SUBMIT-END

没有渲染事件。调查event.detail.fetchResponse.responseturbo:submit-end 似乎完全知道客户端应该重定向,它只是没有。

Response {type: "basic", url: "http://lvh.me:3000/documents/72/labels", redirected: true, status: 200, ok: true, …}
body: (...)
bodyUsed: true
headers: Headers {}
ok: true
redirected: true
status: 200
statusText: "OK"
type: "basic"
url: "http://lvh.me:3000/documents/72/labels"
__proto__: Response

【问题讨论】:

  • 我还尝试使用 data-turbo="true" 启用 Turbo 处理,这会禁用 rails-ujs 表单提交处理,但同样,请求成功后不会发生重定向。
  • 我认为您处于中间状态,这就是它不起作用的原因。你只是想让表单提交像以前一样工作吗?或者您是否尝试使用 turbo 处理表单提交?您的控制器不区分 format.htmlformat.turbo_stream 请求,如果两者都是选项,则需要这样做。如果您只是希望它像之前的 Turbo 一样工作,请禁用提交按钮上的 turbo。有几个关于集成 Hotwire 后链接被“破坏”的问题。 stackoverflow.com/questions/68641396/…
  • 我正在尝试将行为恢复到 Turbo 之前的状态,而无需禁用 Turbo。如果我必须在任何地方禁用它才能使其正常工作,我宁愿不实施它。所以所有的表单提交都需要在他们的操作中使用format.turbo_stream 格式处理?那不是我读的。如果是重定向,它应该重定向。 Turbo 似乎确实意识到它应该这样做。
  • FWIW 我有一个非常接近默认设计会话/新页面的登录页面。我不需要在我的表单上禁用 Turbo,因为表单不在 turbo_frame 标记内。 Turbo 大多只是选择加入。如果您收到 TURBO-STREAM 请求类型,则您的表单可能位于 turbo_frame 内。如果不是,我不确定为什么请求类型被设置为 turbo。
  • 这是一个很好的提示 - 我从一个不在 Turbo 框架内的表单收到一个 Turbo 请求。我放弃了在 Turbo 处于测试阶段时尝试实施它,但当我有修复时我会回到这个问题。

标签: ruby-on-rails turbolinks hotwire-rails


【解决方案1】:

这里发生的情况是,您的应用程序指定它更喜欢 turbo-stream 响应而不是 text/html 响应。如果您要查看重定向页面的请求标头,您可能会看到以下内容:

Accept: text/vnd.turbo-stream.html, text/html, application/xhtml+xml

因此,Rails 返回具有它识别的第一个类型的数据,即text/vnd.turbo-stream.html。浏览器中的 Turbo 会看到这一点,并且由于它不能被解释为 Turbo Stream,因此会默默地忽略它。

解决方案(解决方法?)是确保您重定向到页面的 html 版本:

redirect_to document_labels_path(document_id: @document.id, format: :html)

这将返回 Content-Type 为 text/html 的页面,Turbo 将用内容替换整个页面。

【讨论】:

  • 哇,这很微妙,但很有意义。有没有办法将接受行更改为Accept: text/html, text/vnd.turbo-stream.html, application/xhtml+xml 而不是到处写format: :html?我稍后会试一试,如果可行,将其标记为已接受。
  • 终于回到了这个问题。你是对的。通常可以通过使用turbo_frame_tag 并确保响应为 HTML 格式块来解决此问题。如果您在使用 Devise 时遇到此问题,我的建议是禁用 Devise 表单上的 turbo,直到在 Devise 和 Responders gems 中有官方发布的解决方案。
  • 好的,有趣的转折。在 format.html 块内重定向是不够的。在重定向中将格式指定为 :html 确实会改变 format.html 块中的行为。然而,控制台有Response has no matching &lt;turbo-frame id="new_issue"&gt; element。如果您正在创建新资源,则不会有带有new_resource 的 turbo_frame_tag。仍然不确定如何升级这些表单。
  • @Archonic 三个月后仍然遇到这个问题,正在使用全新的 Rails 7 应用程序。非常令人沮丧的是(我认为)这是开箱即用的。我发现要在create 表单提交上进行重定向,我需要做的最低限度是将render: show 包装在format.html 块内。但像你一样,我宁愿不必记住在任何地方都这样做。你有没有找到避免这种情况的方法?我们缺少某种配置,默认情况下会以 text/html 而不是 text/vnd.turbo-stream.html 响应?
  • @awolfson 我看到的最常见的建议是确保重定向状态为 303,redirect_to whatever_path, status: :see_other。这对我来说从来没有用过,我不知道为什么人们一直建议它。在我的主应用程序中,我仍然在所有具有潜在重定向响应的表单上禁用 turbo - 非常令人失望。此 PR 正在寻找一种合理的方式来解决问题 github.com/hotwired/turbo/pull/445。还有我不推荐的这种可怕的黑客攻击:github.com/hotwired/turbo/issues/138#issuecomment-944711809
【解决方案2】:

补充 Jeff Seifert 的出色回答。

如果您不需要 turbo 流,您也可以完全取消注册 turbo-stream 内容类型,方法是将其放入初始化程序中,例如config/initializers/turbo.rb:

Rails.application.config.after_initialize do
  Mime::Type.unregister(:turbo_stream)
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2015-07-22
    • 1970-01-01
    相关资源
    最近更新 更多