我制作这个刺激控制器只是为了更深入地了解触发什么事件以及何时触发,这是控制器的连接部分:

connect() {
    console.log("controller connected");
    // Turbo Drive Events
    document.addEventListener('turbo:click', () => {
      console.log('turbo:click fired');
    });

    document.addEventListener('turbo:before-visit', () => {
      console.log('turbo:before-visit fired');
    });

    document.addEventListener('turbo:visit', () => {
      console.log('turbo:visit fired');
    });

    document.addEventListener('turbo:visit-start', () => {
      console.log('turbo:visit-start fired');
    });

    document.addEventListener('turbo:visit-received', () => {
      console.log('turbo:visit-received fired');
    });

    document.addEventListener('turbo:before-cache', () => {
      console.log('turbo:before-cache fired');
    });

    document.addEventListener('turbo:before-render', () => {
      console.log('turbo:before-render fired');
    });

    document.addEventListener('turbo:render', () => {
      console.log('turbo:render fired');
    });

    document.addEventListener('turbo:load', () => {
      console.log('turbo:load fired');
    });

    document.addEventListener('turbo:visit-ended', () => {
      console.log('turbo:visit-ended fired');
    });

    document.addEventListener('turbo:frame-load', () => {
      console.log('turbo:frame-load fired');
    });

    // Turbo Stream Events
    document.addEventListener('turbo:before-stream-render', () => {
      console.log('turbo:before-stream-render fired');
    });

    document.addEventListener('turbo:after-stream-render', () => {
      console.log('turbo:after-stream-render fired');
    });

    // Turbo Frame Events
    // Note: 'turbo:frame-load' is already listed under Turbo Drive Events

    // Turbo Form Events
    document.addEventListener('turbo:submit-start', () => {
      console.log('turbo:submit-start fired');
    });

    document.addEventListener('turbo:submit-end', () => {
      console.log('turbo:submit-end fired');
    });
  }

我在页面上有一些表单(不包括它,因为它似乎与问题无关,但如果需要的话,我可以包括它),通过它,我故意不向后端发送正确的信息,因此代码最终在我的Rails控制器中的某个分支条件中结束,这就是那一点:

respond_to do |format|
  format.turbo_stream do
    render turbo_stream: turbo_stream.update('message-space', partial: 'shared/form_errors', locals: { message: @errors })
  end
  format.html { render :edit, status: :unprocessable_entity }
end

提交表单后,我在控制台中记录了这3个错误,我可以在页面上看到错误:

turbo:submit-start fired
turbo:submit-end fired
turbo:before-stream-render fired

换句话说,它告诉我表单提交已开始/结束,即将呈现新的内容.这与上的描述一致:

https://turbo.hotwired.dev/reference/events

我使用的是Rails7.1.2和"热连线/刺激3.2.2"

对于其他事件,我的用例是在turbo流更新页面上的错误内容后,我希望将用户向上滚动到错误内容,因为提交按钮在页面底部,错误显示在页面顶部.

我可能会做一些邪恶的事情与JavaScript事件和诸如此类的事情,以获得上述行为,但我只是好奇这是如何工作的.

我的问题是,为什么其他活动没有启动?或许我对此的理解还未达到标准.

推荐答案

没有turbo:after-stream-render事件(以及turbo:visit-startturbo:visit-receivedturbo:visit-ended).你看到的3个事件就是所有发生的事情.

解决方案是使用Turbo流进行滚动:

respond_to do |format|
  format.turbo_stream do
    render turbo_stream: [
      turbo_stream.update("message-space", partial: "shared/form_errors", locals: {message: @errors}),
      turbo_stream.after(
        "message-space",
        helpers.javascript_tag(%(
          var div = document.querySelector("#message-space");
          div.scrollIntoView({behavior: "smooth"});
        ))
      )
    ]
  end
end

你也可以在shared/_form_errors partial中添加JavaScript,这样你就不需要在你的控制器中做任何改变.


自定义turbo流also/207090">action是alsosolutionevery turbo流problem:

// app/javascript/application.js

Turbo.StreamActions.scroll_to = function () {
  const target = this.targetElements[0];
  target.scrollIntoView({behavior: "smooth"});
};
respond_to do |format|
  format.turbo_stream do
    render turbo_stream: [
      turbo_stream.update("message-space", partial: "shared/form_errors", locals: {message: @errors}),
      turbo_stream.action(:scroll_to, "message-space")
    ]
  end
end

或者,您可以将其设置为方法turbo_stream.scroll_to("message-space"):

# config/initializers/turbo_actions.rb

module CustomTurboStreamActions
  def scroll_to(...)
    action(:scroll_to, ...)
  end

  ::Turbo::Streams::TagBuilder.include(self)
end

100


100

// this is my events.js file i use when trying to figure things out

// NOTE: PREVIEW
// Turbo Drive adds a data-turbo-preview attribute to the <html> element when
// it displays a preview from cache. You can check for the presence of this
// attribute to selectively enable or disable behavior when a preview is
// visible.
// https://turbo.hotwired.dev/handbook/building#detecting-when-a-preview-is-visible
const preview = () =>
  document.documentElement.hasAttribute("data-turbo-preview") || null;

// NOTE: EVENTS
// TODO: morph events for Turbo v8
// https://turbo.hotwired.dev/reference/events

// TURBO:CLICK fires when you click a Turbo-enabled link. The clicked element
// is the event target. Access the requested location with event.detail.url.
// Cancel this event to let the click fall through to the browser as normal
// navigation.
addEventListener("turbo:click", (event) => {
  console.log(preview(), "turbo:click", event);
});

// TURBO:BEFORE-VISIT fires before visiting a location, except when navigating
// by history. Access the requested location with event.detail.url. Cancel this
// event to prevent navigation.
addEventListener("turbo:before-visit", (event) => {
  console.log(preview(), "turbo:before-visit", event);
});

// TURBO:BEFORE-FETCH-REQUEST fires before Turbo issues a network request to
// fetch the page. Access the requested location with event.detail.url and the
// fetch options object with event.detail.fetchOptions. This event fires on the
// respective element (turbo-frame or form element) which triggers it and can
// be accessed with event.target property. Request can be canceled and
// continued with event.detail.resume (see Pausing Requests).
addEventListener("turbo:before-fetch-request", (event) => {
  console.log(preview(), "turbo:before-fetch-request", event);
});

// TURBO:VISIT fires immediately after a visit starts. Access the requested
// location with event.detail.url and action with event.detail.action.
addEventListener("turbo:visit", (event) => {
  console.log(preview(), "turbo:visit", event.detail, event);
});

// TURBO:SUBMIT-START fires during a form submission. Access the FormSubmission
// object with event.detail.formSubmission. Abort form submission (e.g. after
// validation failure) with event.detail.formSubmission.stop(). (use
// event.originalEvent.detail.formSubmission.stop() if you’re using jQuery).
addEventListener("turbo:submit-start", (event) => {
  console.log(preview(), "turbo:submit-start", event);
});

// TURBO:BEFORE-FETCH-RESPONSE fires after the network request completes.
// Access the fetch options object with event.detail. This event fires on the
// respective element (turbo-frame or form element) which triggers it and can
// be accessed with event.target property.
addEventListener("turbo:before-fetch-response", (event) => {
  console.log(preview(), "turbo:before-fetch-response", event);
});

// TURBO:SUBMIT-END fires after the form submission-initiated network request
// completes. Access the FormSubmission object with event.detail.formSubmission
// along with FormSubmissionResult properties included within event.detail.
addEventListener("turbo:submit-end", (event) => {
  console.log(preview(), "turbo:submit-end", event);
});

// TURBO:BEFORE-STREAM-RENDER fires before rendering a Turbo Stream page
// update. Access the new <turbo-stream> element with event.detail.newStream.
// Customize the element’s behavior by overriding the event.detail.render
// function (see Custom Actions).
addEventListener("turbo:before-stream-render", (event) => {
  console.log(preview(), "turbo:before-stream-render", event);
});

// TURBO:BEFORE-CACHE fires before Turbo saves the current page to cache.
addEventListener("turbo:before-cache", (event) => {
  console.log(preview(), "turbo:before-cache", event);
});

// TURBO:BEFORE-RENDER fires before rendering the page. Access the new <body>
// element with event.detail.newBody. Rendering can be canceled and continued
// with event.detail.resume (see Pausing Rendering). Customize how Turbo Drive
// renders the response by overriding the event.detail.render function (see
// Custom Rendering).
addEventListener("turbo:before-render", (event) => {
  console.log(preview(), "turbo:before-render", event);
});

// TURBO:RENDER fires after Turbo renders the page. This event fires twice
// during an application visit to a cached location: once after rendering the
// cached version, and again after rendering the fresh version.
addEventListener("turbo:render", (event) => {
  console.log(preview(), "turbo:render", event);
});

// TURBO:BEFORE-FRAME-RENDER fires before rendering the <turbo-frame> element.
// Access the new <turbo-frame> element with event.detail.newFrame. Rendering
// can be canceled and continued with event.detail.resume (see Pausing
// Rendering). Customize how Turbo Drive renders the response by overriding the
// event.detail.render function (see Custom Rendering).
addEventListener("turbo:before-frame-render", (event) => {
  console.log(preview(), "turbo:before-frame-render", event);
});

// TURBO:FRAME-RENDER fires right after a <turbo-frame> element renders its
// view. The specific <turbo-frame> element is the event target. Access the
// FetchResponse object with event.detail.fetchResponse property.
addEventListener("turbo:frame-render", (event) => {
  console.log(preview(), "turbo:frame-render", event);
});

// TURBO:FRAME-LOAD fires when a <turbo-frame> element is navigated and
// finishes loading (fires after turbo:frame-render). The specific
// <turbo-frame> element is the event target.
addEventListener("turbo:frame-load", (event) => {
  console.log(preview(), "turbo:frame-load", event);
});

// TURBO:FRAME-MISSING fires when the response to a <turbo-frame> element
// request does not contain a matching <turbo-frame> element. By default, Turbo
// writes an informational message into the frame and throws an exception.
// Cancel this event to override this handling. You can access the Response
// instance with event.detail.response, and perform a visit by calling
// event.detail.visit(...).
addEventListener("turbo:frame-missing", (event) => {
  console.log(preview(), "turbo:frame-missing", event);
});

// TURBO:FETCH-REQUEST-ERROR fires when a form or frame fetch request fails due
// to network errors. This event fires on the respective element (turbo-frame
// or form element) which triggers it and can be accessed with event.target
// property. This event can be canceled.
addEventListener("turbo:fetch-request-error", (event) => {
  console.log(preview(), "turbo:fetch-request.error", event);
});

// TURBO:LOAD fires once after the initial page load, and again after every
// Turbo visit. Access visit timing metrics with the event.detail.timing
// object.
addEventListener("turbo:load", (event) => {
  console.log(preview(), "turbo:load", event);
});

Javascript相关问答推荐

React:未调用useState变量在调试器的事件处理程序中不可用

硬币兑换运行超时

如何用显示网格平滑地将元素从一个地方移动到另一个地方?

我不知道为什么setwritten包装promise 不能像我预期的那样工作

判断表格单元格中是否存在文本框

如何找出摆线表面上y与x相交的地方?

在Vite React库中添加子模块路径

我在我的Java代码中遇到了问题,代码的一部分看不到先前定义的对象

虚拟滚动实现使向下滚动可滚动到末尾

在HTML语言中调用外部JavaScript文件中的函数

本地库中的chartjs-4.4.2和chartjs-plugin-注解

Puppeteer上每页的useProxy返回的不是函数/构造函数

在画布中调整边上反弹框的大小失败

无法避免UV:flat的插值:非法使用保留字"

在SHINY R中的嵌套模块中,不能使用Java代码

当代码另有说明时,随机放置的圆圈有时会从画布上消失

无法重定向到Next.js中的动态URL

使用可配置项目创建网格

Firefox的绝对定位没有达到预期效果

如何调整下拉内容,使其不与其他元素重叠?