添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
纯真的石榴  ·  Openproject - Error ...·  1 周前    · 
想发财的镜子  ·  신형 카마그라 젤 ...·  3 周前    · 
刚分手的红薯  ·  Attempting Fresh ...·  4 周前    · 
神勇威武的红茶  ·  Fresh butter and ...·  1 月前    · 
挂过科的椰子  ·  How to modify the ...·  1 月前    · 
拉风的楼房  ·  《战乙女苏菲亚 ...·  3 月前    · 
光明磊落的消防车  ·  Search Results | ...·  5 月前    · 
爱喝酒的牛肉面  ·  利用FRP+CS实现Kali ...·  7 月前    · 

I’ve successfully implemented a search form (i.e. a text input field) that changes the src attribute value of a <turbo-frame> element (which one automatically fetches and renders data immediately after the change). The search result rendered in the <turbo-frame> is a <ul><li> list.

Now, I want to add a custom attribute (i.e. setAttribute() ) to the <li> list elements each time after the search result is loaded/rendered.

I tried to use addEventListener() (on Stimulus controller, document and window with Turbo events and non-Turbo events), the built-in Stimulus function afterLoad and some other weird things (e.g. MutationObserver ) without success.

How to modify the content present in the <turbo-frame> after it is freshly loaded/rendered?

Here is a Stimulus controller code example using event listeners:

// app/javascript/controllers/search_controller.js
import { Controller } from "@hotwired/stimulus";
// Connects to data-controller="search"
export default class extends Controller {
  static targets = ["field", "resultTurboFrame", "item"];
  connect() {
    // These event listeners do not fire at all:
    this.resultTurboFrameTarget.addEventListener("turbo:frame-load", this.resultHandler);
    document.addEventListener("turbo:frame-load", this.resultHandler);
    window.addEventListener("turbo:frame-load", this.resultHandler);
    this.resultTurboFrameTarget.addEventListener("turbo:frame-render", this.resultHandler);
    document.addEventListener("turbo:frame-render", this.resultHandler);
    window.addEventListener("turbo:frame-render", this.resultHandler);
    this.resultTurboFrameTarget.addEventListener("turbo:before-frame-render", this.resultHandler);
    document.addEventListener("turbo:before-frame-render", this.resultHandler);
    window.addEventListener("turbo:before-frame-render", this.resultHandler);
    this.resultTurboFrameTarget.addEventListener("turbo:before-render", this.resultHandler);
    document.addEventListener("turbo:before-render", this.resultHandler);
    window.addEventListener("turbo:before-render", this.resultHandler);
    // These event listeners fire but I cannot modify the fresh 
    // loaded/rendered content because event.target.querySelectorAll("li") 
    // returns an empty NodeList which length is 0 i.e. <li> elements are not recognized
    this.resultTurboFrameTarget.addEventListener("turbo:before-fetch-response", this.resultHandler);
    document.addEventListener("turbo:before-fetch-response", this.resultHandler);
    window.addEventListener("turbo:before-fetch-response", this.resultHandler);
    this.resultTurboFrameTarget.addEventListener("turbo:before-fetch-request", this.resultHandler);
    document.addEventListener("turbo:before-fetch-request", this.resultHandler);
    window.addEventListener("turbo:before-fetch-request", this.resultHandler);
    this.resultTurboFrameTarget.addEventListener("turbo:before-stream-render", this.resultHandler);
    document.addEventListener("turbo:before-stream-render", this.resultHandler);
    window.addEventListener("turbo:before-stream-render", this.resultHandler);
    // Other non-working attempts that fire but I cannot modify the fresh
    // for the above-mentioned reasons.
    this.boundedResultHandler = this.resultTurboFrameHandler.bind(this)
    this.searchResultFrameTarget.addEventListener("turbo:before-fetch-response", this.boundedResultHandler);
    document.addEventListener("turbo:before-fetch-response", this.boundedResultHandler);
    window.addEventListener("turbo:before-fetch-response", this.boundedResultHandler);
  disconnect() {
    this.resultTarget.removeEventListener("turbo:frame-render", this.resultHandler);
    // ... 
  resultHandler(event) {
   console.log("Should modify content after it is freshly loaded/rendered, but doesn't work");
    event.target.querySelectorAll("li").forEach((li) => { 
      li.setAttribute("loaded", true); // <li loaded="true"></li>

The .erb file returned by the search request is like this (note: actually, if this can be the problem but I think it’s not, the response to the search fetch request is a <turbo-stream><template><ul><li>...</template></turbo-stream> which properly loads/renders the content):

<turbo-stream action="update" target="search_turbo_frame_id"><template>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
      <li>Item ...</li>
</template></turbo-stream>