提问人:Backo 提问时间:3/28/2023 最后编辑:Backo 更新时间:3/28/2023 访问量:710
如何修改<turbo-frame>元素中存在的新鲜加载/渲染内容?
How to modify the fresh loaded/rendered content present in a <turbo-frame> element?
问:
我已经成功地实现了一个搜索表单(即文本输入字段),该表单更改了 <turbo-frame>
元素的 src
属性值(该元素在更改后立即自动获取并呈现数据)。中呈现的搜索结果是一个列表。<turbo-frame>
<ul><li>
现在,我想在每次加载/呈现搜索结果后向列表元素添加一个自定义属性(即 setAttribute())。<li>
我尝试使用 addEventListener()(在 Stimulus 控制器、带有 Turbo 事件和非 Turbo 事件的文档和窗口上)、内置的 Stimulus 函数 afterLoad 和其他一些奇怪的东西(例如 MutationObserver)但没有成功。
如何修改新加载/渲染后存在的内容?<turbo-frame>
答:
0赞
Alex
3/28/2023
#1
您不必自己设置,只需添加到表单中并提交即可。src
turbo_frame: "name"
bin/rails g scaffold Item name
bin/rails db:migrate
bin/rails g stimulus search
# app/controllers/items_controller.rb
def index
@items = if params[:search].present?
Item.where(Item.arel_table[:name].matches("%#{params[:search]}%"))
else
Item.all
end
end
# app/views/items/index.html.erb
<%= tag.div data: {controller: "search"} do %>
<%= form_with url: :items, method: :get,
data: {search_target: "form", turbo_frame: :items} do |f| %>
<%# NOTE: target the frame ^^^^^^^^^^^^^^^^^^^ %>
<%= f.search_field :search, placeholder: "search...",
data: {action: "search#autoSearch"} %>
<% end %>
<%= turbo_frame_tag :items, target: :_top,
data: {search_target: "results", turbo_action: :advance} do %>
<%# NOTE: to update url as well ^^^^^^^^^^^^^^^^^^^^^^ %>
<%= render @items %>
<% end %>
<% end %>
// app/javascript/controllers/search_controller.js
import { Controller } from "@hotwired/stimulus";
// Connects to data-controller="search"
export default class extends Controller {
static targets = ["form", "results", "item"];
connect() {
this.resultsTarget.addEventListener("turbo:frame-render", this.resultsHandler);
}
resultsHandler(event) {
event.target.querySelectorAll("li").forEach((li) => {
li.setAttribute("loaded", true); // <li loaded="true"></li>
});
}
autoSearch() {
// don't search on every keystroke
clearTimeout(this.timeout);
this.timeout = setTimeout(() => this.formTarget.requestSubmit(), 500);
}
// NOTE: you can also add a target and use target callbacks
// <li data-search-target="item"> </li>
itemTargetConnected(element) {
// to skip initial page load
if (this.resultsTarget.src) {
element.setAttribute("loaded", true);
}
}
disconnect() {
this.resultsTarget.removeEventListener("turbo:frame-render", this.resultsHandler);
}
}
https://stimulus.hotwired.dev/reference/targets#connected-and-disconnected-callbacks
与其在控制器内添加事件侦听器,不如使用:data-action
<%= turbo_frame_tag :items, target: :_top,
data: {
turbo_action: :advance,
action: "turbo:frame-render->search#resultsHandler"
} do %>
<%= render @items %>
<% end %>
评论
0赞
Backo
3/29/2023
即使在 HTML5 中可能,为了保持简单,我也不想使用嵌套表单(仅供参考,我正在使用嵌套到表单中的搜索字段)。但是,不会被调用(顺便说一句)。这就是我提出这个问题的原因之一(网络上还有其他关于这个问题的问题)。实际上,如果这可能是问题所在(但我认为不是),那么对搜索获取请求的响应是正确加载/呈现内容的响应。turbo:frame-render
turbo:before-fetch-response
<turbo-stream action="update" target="search_turbo_frame_id"><template><ul><li>...</template></turbo-stream>
0赞
Backo
3/29/2023
通过使用 和 Turbo 事件(注意:唯一触发的事件),返回一个长度为 0 的空 NodeList,即 元素无法识别。turbo:before-fetch-response
turbo:before-fetch-request
event.target.querySelectorAll("li")
<li>
0赞
Alex
3/30/2023
@Backo你必须展示你的代码,这样我才能看到你在做什么。您在问题中说了一件事,在评论中说了完全不同的事情,我现在看不出涡轮增压框架与它有什么关系。 应该在您可以访问流的地方工作,并且可以根据需要进行更改。turbo:before-stream-render
评论