出现“内容丢失”的 Turbo Frame 错误

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。

  • `data: {turbo_frame: "_top"}` 是我正在寻找的。谢谢。 (3认同)

Ale*_*lex 5

当您在表单提交后重定向时,没有<turbo-frame>具有相同 id 的表单,因此您会收到帧丢失错误。有关一些详细信息和我第一次尝试可重用的解决方案:

/sf/answers/5299314261/

我不想发布重复的答案,但我会提到有一个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.redirect操作

“重定向”操作的标签如下所示:

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