没有turbo:after-stream-render
事件(以及turbo:visit-start
、turbo:visit-received
、turbo: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是also和solution到every 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);
});