Event to know a `turbo-stream` has been rendered

The turbo:load event does not emit when the response contains a turbo-stream, which maybe is correct, since it is not a complete page load (not 100% sure).

However, I am not able to find any event that notifies me when a turbo stream has been rendered to the DOM, so that I can perform some DOM related stuff on that node


turbo:before-stream-render. :slight_smile:

(PR to get the new template included in the event.)

I am looking for after. Coz I want to select the DOM nodes from this new stream HTML. :slight_smile:

I believe the newTemplate will just be a raw string. What I want is to write document.querySelector('some-node-from-stream-html')

1 Like

Ah! Sorry, misread. Could submit a PR for a new one?

The newTemplate is a DocumentFragment. :slight_smile:

No worries :). Will create a PR, just waiting to see if the team wants it in or not

1 Like

There’s no built-in event for notification after a Turbo Streams render.

Instead, add a Stimulus data-controller attribute to the element you render inside the <turbo-stream> element. Then implement the connect() method on that controller to know when the element has been loaded into the document.


Having this as a short term solution is fine. But doesn’t seems like a perfect approach.

On a side note, is there any specific reason for not dispatching an event ?

The specific reason is to encourage you to design your application not to care about where new HTML comes from or how it gets into the document :blush:

1 Like

I thought of having this as a companion to the turbo:load event, but for streams. All the use cases that turbo:load solves for a regular visit, this non-existing event will solve for streams.

Maybe I am missing something obvious here. But this is my primary motivation

The turbo:load event dates all the way back to 2012 when it was called page:load. We used it as a way to initialize jQuery plugins and other JavaScript behavior when the page changed.

The world has moved on since then, and we now have MutationObserver to detect changes to the DOM, and libraries like Stimulus that present a nice API on top. That’s what we’re designing for.

1 Like

This is interesting, I too was looking for the event listeners approach, but I’m curious on how I can achieve this with stimulus. Is there a way with stimulus to react to a child node being removed?

@perezperret, you could make the child that may disappear a target and then check for the presence of the target in an action.

If you want to constantly be monitoring for changes to children in the DOM tree, you likely need a custom mutation observer with childList set to true.

You can put a controller on the element and implement the disconnect() method to do something when it’s removed from the page.


Is there any documentation on how to use that API? I can’t seem to find any docs on how to use them (@stimulus/mutation-observers).

1 Like

To be clear, the API I’m referring to is the set of Lifecycle Callbacks available to Stimulus controllers. The @stimulus/mutation-observers package is how that’s implemented.

All, this seems fine it you are using StimulusJS as your framework. But that’s not the case for us. We are in the process of implementing Hotwire for asynchronous UI updates in an existing application.

Our existing Javascript code has a hook that needs to be ran whenever new content is inserted into the page. It looks for matching DOM entries, and enables the JS needed for the things like date pickers, fancier select controls etc.

All we need to hook this up is an event that is fired after a stream is rendered. Ideally with the DOM element on the newly inserted content, but even that isn’t strictly necessary.

From what’s been said it sounds like the proposed solution would mean that we would have to rewrite all our existing JS code to use stimulus controllers, and that’s probably not tenable.

Is there any chance you could reconsider this event?

If not I’m not sure what other options are available to us (maintaining a fork maybe?)


What is the solution if we don’t want to use Stimulus?

@samstickland Why wouldn’t it be tenable to rewrite to Stimulus? It sounds like your JS is structured in such a way - DOM manipulation of nodes created after DOMContentLoaded - that Stimulus would be a match made in heaven. Sure, every migration to new tech takes time and testing, but you need to fix your javascript anyway. It’s also very easy to implement - you can probably keep most of your code and wrap it in the connect() { JS CODE HERE } method on a per-controller basis. Just add a data-controller="dropdown" to the DOM node in question, and put your code in a dropdown_controller.js and you won’t need an event at all.

If you really don’t want to add Stimulus to your project for this, it’s not like Stimulus is doing anything truly magic here. You can observe the relevant part of the DOM with your own Mutation Observer code and run the code on newly created elements when they appear in the DOM. Here’s a nice vanilla JS example I found through twenty seconds of googling. This is similar to what Stimulus is doing under the hood.

(Also, nitpick: you say you’re implementing Hotwire, but Hotwire includes Stimulus. You probably mean Turbo.)

@n-studio One solution is using Mutation Observers directly, see above.