I am using Turbo Frames in my Rails app and have, on every page
<turbo-frame id="messagesFrame" src="/chats">
</turbo-frame>
This loads in fine, and when a link is clicked replaces the frame as expected. In this frame I have set overflow-y: scroll
, creating a scrollable frame on the page. Every time a new page is loaded in the frame, I want it to scroll to the bottom. How can I achieve this? Ideally with vanilla JavaScript.
You could do this in several ways.
Turbo should fire a turbo:before-fetch-request
and turbo:before-fetch-response
on the document
when lazy loaded frames, or links that trigger a frame reload.
You could do something like:
document.addEventListener("turbo:before-fetch-response", function (e) {
let frame = document.getElementById("messagesFrame");
if (frame.complete) {
frame.scrollTo(0, frame.scrollHeight)
} else {
frame.loaded.then(() => frame.scrollTo(0, frame.scrollHeight))
}
})
Sources: Turbo events => https://turbo.hotwired.dev/reference/events
Frame.complete and Frame.loaded => https://turbo.hotwired.dev/reference/frames
I suggest the above method because you specified vanilla Javascript. The recommended way for most Turbo related things is to use StimulusJS.
You could write a Stimulus (https://stimulus.hotwired.dev/) controller that you attach to an element in the body that shows inside the TurboFrame, and in the connect
method, do the same.
That way, whenever the content inside the frame is refreshed the Stimulus controller will run, and you don't have to worry about the order of the events being fired.