fol*_*zyk 12 ruby-on-rails hotwire-rails turbo-rails turbo-frames ruby-on-rails-7
我正在尝试在 Rails 应用程序中使用turbo_frame_tag 来管理一些任务。我为我的任务创建了一个脚手架。
我将要使用的页面包装在 Turbo 框架标签内,如下所示:
<%= turbo_frame_tag "modal" do %>
<h1>New task</h1>
<%= render "form", task: @task %>
<br>
<div>
<%# <%= link_to "Back to tasks", tasks_path %> %>
<%= link_to "Cancel", "#", data: {
controller: "modals",
action: "modals#close"
}, class: "cancel-button" %>
</div>
<% end %>
Run Code Online (Sandbox Code Playgroud)
在我的主页 index.html.erb 文件中,我使用相同的标签将数据添加到“添加”按钮:
<%= link_to "Add", new_task_path, data: { turbo_frame: "modal" }, class: "btn btn-secondary", remote: true %>
Run Code Online (Sandbox Code Playgroud)
该模式工作正常。当我单击主页上的“添加”按钮时,它将打开。当我尝试提交操作来创建新任务时,我在终端上看到 200 响应,并且新任务已添加到我的数据库中。
但是(也)我在主页上收到“内容缺失”文本信息。该页面未重新加载。在开发者浏览器中我收到此错误:
<%= turbo_frame_tag "modal" do %>
<h1>New task</h1>
<%= render "form", task: @task %>
<br>
<div>
<%# <%= link_to "Back to tasks", tasks_path %> %>
<%= link_to "Cancel", "#", data: {
controller: "modals",
action: "modals#close"
}, class: "cancel-button" %>
</div>
<% end %>
Run Code Online (Sandbox Code Playgroud)
我刚刚开始学习 Ruby on Rails,一切对我来说都是新的。如果有人遇到这样的问题以及如何处理它,我将不胜感激任何帮助和信息。
Tho*_*der 12
此PR中介绍并记录了此行为。请注意,hotwire 文档已更新为推荐的解决方案。
Content Missing您可以通过添加 [turbo 访问控制标记] ( https://turbo.hotwired.dev/reference/attributes#meta-tags )来指定页面应重定向而不是呈现错误。
为了使它更容易,您可以使用涡轮辅助方法。
<!-- show.html.erb -->
<meta name="turbo-visit-control" content="reload">
<!-- or -->
<%= turbo_page_requires_reload %>
Run Code Online (Sandbox Code Playgroud)
或者,您可以显式添加data: {turbo_frame: "_top"}来指定链接应脱离turbo_frame。
当您在表单提交后重定向时,没有<turbo-frame>具有相同 id 的表单,因此您会收到帧丢失错误。有关一些详细信息和我第一次尝试可重用的解决方案:
我不想发布重复的答案,但我会提到有一个turbo:frame-missing事件,您可以监听并处理错误:
document.addEventListener("turbo:frame-missing", (event) => {
const { detail: { response, visit } } = event;
event.preventDefault();
visit(response.url);
});
Run Code Online (Sandbox Code Playgroud)
进行简单操作时需要注意的visit(response.url)是,这将是对该 url 的第二个请求(第一个请求来自重定向)。
处理此问题的理想位置是重定向响应,因为您可以在此处知道表单提交是否成功,并将重定向作为常规的Turbo.visit框架外部发送。您可以通过在turbo_stream中发送一些javascript来做到这一点:
render turbo_stream: turbo_stream.append(
request.headers["Turbo-Frame"],
helpers.javascript_tag(
"Turbo.visit('#{model_url(@model)}')",
data: {turbo_temporary: true} # one time only; don't cache it
)
)
Run Code Online (Sandbox Code Playgroud)
为了让它更漂亮一点,做同样的事情,但是在自定义涡轮流动作中。
“重定向”操作的标签如下所示:
<turbo-stream action="redirect" target="/url"></turbo-stream>
Run Code Online (Sandbox Code Playgroud)
向Turbo添加新操作以在前端处理它:
https ://turbo.hotwired.dev/handbook/streams#custom-actions
// app/javascript/application.js
import { Turbo } from "@hotwired/turbo-rails";
Turbo.StreamActions.redirect = function () {
Turbo.visit(this.target);
};
// or using event listener
document.addEventListener("turbo:before-stream-render", (event) => {
const fallbackToDefaultActions = event.detail.render;
event.detail.render = function (streamElement) {
if (streamElement.action == "redirect") {
Turbo.visit(streamElement.target);
} else {
fallbackToDefaultActions(streamElement);
}
};
});
Run Code Online (Sandbox Code Playgroud)
使用通用action方法在控制器或模板中渲染它:
turbo_stream.action(:redirect, model_url(@model))
Run Code Online (Sandbox Code Playgroud)
您还可以redirect向助手添加方法turbo_stream:
# config/initializers/stream_actions.rb
module CustomTurboStreamActions
# turbo_stream.redirect(model_url(@model))
def redirect url
action(:redirect, url)
end
end
Turbo::Streams::TagBuilder.include(CustomTurboStreamActions)
Run Code Online (Sandbox Code Playgroud)
如何跳出框架的示例:
# app/controllers/*_controller.rb
def update
respond_to do |format|
if @model.update(model_params)
format.turbo_stream do
render turbo_stream: turbo_stream.redirect(model_url(@model))
end
format.html { redirect_to model_url(@model), notice: "Updated." }
else
format.html { render :edit, status: :unprocessable_entity }
end
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7802 次 |
| 最近记录: |