ruby-on-rails 出现Turbo帧错误“内容丢失”

ldfqzlk8  于 2023-03-20  发布在  Ruby
关注(0)|答案(1)|浏览(188)

我尝试在我的rails应用中使用turbo_frame_tag来管理一些任务,我为我的任务创建了一个scaffold。
我 Package 的网页,我想使用内的涡轮增压帧标记如下:
〈%= turbo_frame_tag“模态”执行%〉

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

〈%结束%〉
enter image description here
在我的主页index.html.erb文件中,我使用相同的标记将数据添加到Add按钮:
<%= link_to "Add", new_task_path, data: { turbo_frame: "modal" }, class: "btn btn-secondary", remote: true %>
模态工作正常。当我点击主页上的添加按钮时,它被打开。当我尝试提交我的操作以创建新任务时,我在终端上看到200响应,新任务被添加到我的数据库中。
但是(也)我得到了“内容丢失”的文本信息在我的主页上。该页是不重新加载。在开发者浏览器中,我得到这个错误:
turbo.es2017-esm.js:3650 Uncaught (in promise) Error: The response (200) did not contain the expected \<turbo-frame id="modal"\> and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload. at c.delegateConstructor.throwFrameMissingError (turbo.es2017-esm.js:3650:15) at c.delegateConstructor.handleFrameMissingFromResponse (turbo.es2017-esm.js:3646:14) at c.delegateConstructor.loadFrameResponse (turbo.es2017-esm.js:3567:18) at async c.delegateConstructor.loadResponse (turbo.es2017-esm.js:3441:34)
enter image description here
我刚开始学习Ruby-on-rails,对我来说一切都是新的。如果有人遇到这样的问题,以及如何处理它,我将非常感谢任何帮助和信息。

v8wbuo2f

v8wbuo2f1#

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

  • 一个月一次 *

我不想发布重复的答案,但我会提到有一个turbo:frame-missing事件,您可以监听并处理错误:

document.addEventListener("turbo:frame-missing", (event) => {
  const { detail: { response, visit } } = event;
  event.preventDefault();
  visit(response.url);
});

做一个简单的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
  )
)

为了使它更漂亮一点,做同样的事情,但在一个自定义涡轮流的行动。

自定义 turbo_stream.redirect 操作

“redirect”操作的标记如下所示:

<turbo-stream action="redirect" target="/url"></turbo-stream>

Turbo 中添加新操作,以便在前端进行处理:

  • 网址:http: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);
    }
  };
});

使用泛型action方法在控制器或模板中渲染它:

turbo_stream.action(:redirect, model_url(@model))

您也可以将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)

如何跳出框架的示例:

# 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

相关问题