使用 Hotwire(Stimulus / Turbo / Rails)重新加载 Turbo 帧。

3

我最近一个月或两个月一直在使用Hotwire,并尝试了解如何在第一次渲染后重新加载特定的turbo-frame。

假设我有一个简单的Rails控制器用于用户搜索。如果它具有name参数,则返回与该name匹配的用户,否则返回所有用户。

class UserSearchController
  def show
    return User.where(name: params[:name]) if params[:name].present?

    return User.all
  end
end

我连接了一个Turboframe,它可以正确地惰性加载DOM中的所有用户。我正在尝试弄清楚如何更新该Turboframe并重新绘制框架。我已经尝试过使用Stimulus并尝试将src设置为端点,这是其他帖子中提出的建议:

  reload() {
    const {src: src} = this;
    this.src = null;
    this.src = src;
  }

不过那似乎不起作用,它没有重新绘制 turboframe。但我可以看到它正在向 rails 后端进行请求。

是否有人能够指导我在页面加载后重新加载/重绘框架的方向?我不确定自己是完全错了还是已经接近正确。

2个回答

4

在那个 show 操作或者 render locals: {.. 中,你需要一些实例变量,否则你将返回空值。在 stimulus 控制器中,this 指的是控制器实例,在没有看到其余部分的情况下,它看起来好像什么也没做。

将此复制到任何页面并单击以重新加载:

<%= turbo_frame_tag :reloadable, style: "display:none;" do %>
  <%= request.uuid %>
<% end %>

# clicking this frame will load that ^ frame, because it's first.
<%= turbo_frame_tag :reloadable, src: request.url, onclick: "reload()" %>

重复的ID,我知道。把它放在不同的页面上,就不会再重复了。


因为 onclick 不是一个很酷的事情:

// app/javascript/controllers/hello_controller.js

import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  reload() {
    this.element.reload();

    // this works as well
    // this.element.src = this.element.src;

    // not sure if you would ever need to do it this way
    // this.element.removeAttribute("complete");
  }
}

<%= turbo_frame_tag(:reloadable, style: "display:none;") { request.uuid } %>

<%= turbo_frame_tag :reloadable, src: request.url,
  data: {
    controller: "hello",
    action: "click->hello#reload"
  }
%>

https://turbo.hotwired.dev/reference/frames#functions


关于搜索表单:
# app/views/any/where.html.erb

<%= form_with url: "/users", method: :get,
  data: {turbo_frame: :users} do |f| %>

  <%= f.search_field :name, placeholder: "search by name" %>
  <%= f.button "Search" %>
<% end %>

# load this frame from `src`. load it again from the form submission response.
<%= turbo_frame_tag :users, src: "/users", target: :_top %>

# app/views/users/index.html.erb

<%
  scope = User.all
  scope = scope.where(name: params[:name]) if params[:name].present?
  @users = scope
%>

<%= turbo_frame_tag :users, target: :_top do %>
  <% @users.each do |user| %>
    <%= user.name %>
  <% end %>
<% end %>

https://turbo.hotwired.dev/handbook/frames#targeting-navigation-into-or-out-of-a-frame


谢谢。我应该在控制器示例中更清楚。我已经返回实例变量了。我只是想确保在我的问题中展示它可以返回混合数据。我已确认端点有效。它在初始页面加载时正常加载。只是当我尝试像你提到的“重新加载”或“设置src”时,框架不会重新加载。根据您提供的信息,这种方法似乎应该奏效。就像我提到的那样,我也可以看到请求进入Rails,只是它不会重新加载框架。 - D1D2D3D4D5
感谢 @alex 的回复。 - D1D2D3D4D5
如果收到响应,您需要检查浏览器控制台是否有任何错误。同时,您确定响应确实不同吗?如果是相同的响应,它看起来就像什么都没有发生过一样。 - Alex
没有错误,我可以看到请求成功地进入了Rails并进行处理,只是没有DOM更新。返回的响应也不同,这就是我提到显示控制器返回混合数据的原因 :)明天我会再试一次,看看情况如何。然后我可以提供更多细节,或者通过更新来解决线程。顺便说一句,我正在惰性加载这些框架。我读到设置src可能会有差异,但我认为这不应该完全阻止框架重新渲染。 - D1D2D3D4D5
好的,我在这方面有了一些进展,但不确定问题出在哪里。我可以确认设置src会重新渲染框架(耶)。问题是,当我附加查询参数时,它们在到达rails时就丢失了。我可以确认,一般情况下端点接受查询参数没有问题(在Postman中测试过)。为什么使用带有查询参数的Turboframe的src会在提交到rails时丢失它们?我可以看到rails端的入站请求没有它们,所以它只是一遍又一遍地重新呈现第一个结果。 - D1D2D3D4D5
1
已解决。最后的问题出在我这里。在向数据存储发送请求之前,我没有正确地从我的应用程序构建请求。谢谢,感谢您的帮助。 - D1D2D3D4D5

0
你试过移除 <turbo_frame> DOM 元素的 loaded 属性吗?这样应该会触发重新加载动作,使用 src 属性中指定的路径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接