一点前言。如果您只是需要跳出框架,请参阅其他答案,或阅读docs https://turbo.hotwired.dev/reference/attributes: data-turbo-frame
属性就是你所需要的。这个答案是当你想要的时候有条件的根据表单提交期间发生的情况跳出框架。
这是“新”的Turbo v7.3.0 https://github.com/hotwired/turbo/releases/tag/v7.3.0 (涡轮导轨 v1.4.0 https://github.com/hotwired/turbo-rails/releases/tag/v1.4.0),帧丢失时的重定向行为将恢复为永远停留在帧中的原始方式。
有一个turbo:frame-missing
发出事件以便您可以自定义此行为:
turbo:frame-missing
- 当响应时触发<turbo-frame>
元素请求不包含匹配的<turbo-frame>
元素。
默认情况下,Turbo 将信息性消息写入帧中并
抛出异常。取消此事件以覆盖此处理。你
可以访问Response
实例与event.detail.response
, 和
通过致电进行访问event.detail.visit(...)
https://turbo.hotwired.dev/reference/events https://turbo.hotwired.dev/reference/events
像这样:
document.addEventListener("turbo:frame-missing", (event) => {
const { detail: { response, visit } } = event;
event.preventDefault();
visit(response.url);
});
虽然这有效,但它会向服务器发出另一个请求,这正是以前发生的情况。
如果您只想显示重定向的响应,您可以visit
the response
:
document.addEventListener("turbo:frame-missing", (event) => {
const { detail: { response, visit } } = event;
event.preventDefault();
visit(response); // you have to render your "application" layout for this
});
Turbo 帧请求用于在没有布局的情况下进行渲染,现在它们render https://github.com/hotwired/turbo-rails/blob/v1.4.0/app/controllers/turbo/frames/frame_request.rb#L24微小的范围内layout https://github.com/hotwired/turbo-rails/blob/v1.4.0/app/views/layouts/turbo_rails/frame.html.erb. response
必须是整页响应才能访问,否则,turbo会刷新页面,这会让情况变得更糟。这可以修复它:
def show
render layout: "application"
end
自定义涡轮流重定向解决方案:
https://stackoverflow.com/a/75750578/207090 https://stackoverflow.com/a/75750578/207090
我认为它比下面的解决方案更简单。
设置自定义标题
这让您可以在前端选择是否以及何时想要突破框架。
使用控制器操作名称设置数据属性,例如data-missing="controller_action"
(或您需要的任何其他触发器,例如控制器名称):
<%= turbo_frame_tag "form_frame", data: { missing: "show" } do %>
# ^
# this is where missing frame is expected, it's not strictly
# necessary, but it's where "application" layout is required
这更像是一种“我想知道这是否可行”类型的解决方案,只需确保您需要它:
// app/javascript/application.js
addEventListener("turbo:before-fetch-request", (event) => {
const headers = event.detail.fetchOptions.headers;
// find "#form_frame[data-missing]"
const frame = document.querySelector(`#${headers["Turbo-Frame"]}[data-missing]`);
if (frame) {
// if frame is marked with `data-missing` attribute, send it with request
headers["X-Turbo-Frame-Missing"] = frame.dataset.missing;
}
});
addEventListener("turbo:frame-missing", (event) => {
const { detail: { response, visit } } = event;
if (response.headers.get("X-Turbo-Frame-Missing")) {
// if response has "frame missing" header it can be rendered
// because we'll make sure it's rendered with a full layout
event.preventDefault();
visit(response);
}
});
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
layout -> {
if turbo_frame_request?
# check if we are in an action where a missing frame is
# if you're jumping between controllers, you might need to
# have controller name in this header as well
if request.headers["X-Turbo-Frame-Missing"] == action_name
# let `turbo:frame-missing` response handler know it's ok to render it
headers["X-Turbo-Frame-Missing"] = true
# because it's a full page that can be displayed
"application"
else
"turbo_rails/frame"
end
end
}
end
https://turbo.hotwired.dev/handbook/frames#break-out-from-a-frame https://turbo.hotwired.dev/handbook/frames#%E2%80%9Cbreaking-out%E2%80%9D-from-a-frame
https://github.com/hotwired/turbo/pull/863 https://github.com/hotwired/turbo/pull/863