Reputation: 38878
I am sending a Form via TurboStream. When the response is finished, and the Stream element has been rendered, I must react to modify part of the Doom. This logic doesn't belong to the new rendered element, so I don't want to put it there in the connect
method.
I would like to receive an event or some signal that tells me the new element has been received and rendered.
I see there is no plan to add an after-stream-render event.
How can I know when the new element has been rendered?
Upvotes: 0
Views: 46
Reputation: 38878
The most common suggestion is to add a Stimulus controller in the rendered element and use the connect()
method to do whatever you want. But this is polluting the new element's controller with logic that doesn't belong to it.
I come out with a compromised solution. Yes, I add a Stimulus controller in the rendered element, but this Stimulus controller is very lean and generic, so it can be reusable, and the logic that reacts to the event is in another specialized controller.
This is the generic solution I am using:
I have a reusable controller that triggers a CustomEvent
.
The value of the CustomEvent is configurable via data-value
attribute:
// app/javascript/controllers/i_am_here_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static values = {
eventName: String
}
connect() {
const trigger = new CustomEvent(this.eventNameValue);
window.dispatchEvent(trigger);
}
}
In the element that is rendered with the TurboStream I connect this controller:
<div
data-controller="i-am-here"
data-i-am-here-event-name-value="my-element-rendered"
>
/* edited */
</div>
Now I just have to listen to this event in another controller which is responsible to react to when the content is loaded:
// app/javascript/controllers/reaction_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
window.addEventListener("my-element-rendered", this.react.bind(this));
}
react() {
console.log("Here I can react");
}
}
Upvotes: 0