I have a stimulus controller that handles the behavior of a slide out element on a given page. In many cases, it contains a form, and after the form is successfully submitted, I usually want to close the slide out.
Additionally, the the form submission usually results in the update of a <turbo-frame>
somewhere else on the page.
My question is, what is the best way to listen for the update to the turbo frame, and then trigger my stimulus controller to close the slide out?
My first thought was that it would be nice to do something like this:
<%= turbo_frame_tag(
program,
data: { action: 'turbo:frame-render->slide-out#close' },
class: 'program',
) %>
But to my understanding, this won’t work because it’s not wrapped within the <div data-controller='slide-out'>
element.
As an aside, it’s not totally clear to me whether or not turbo:frame-render
is even a valid type of event for a stimulus action attribute. And it turns out that this event doesn’t get triggered from a turbo stream. The only event I could discover was turbo:before-stream-render
.
At any rate, here is the best solution I’ve been able to come up with so far:
- Make the controller easily accessible from the element with this:
connect() {
this.element[this.identifier.camelCase()] = this
}
- Listen globally for the
turbo:before-stream-render
event, then call theclose()
method if the right elements exist on the page.
$(document).on 'turbo:before-stream-render', (e) ->
if $('.program').length
$('[data-controller="slide-out"]')[0].slideOut.close()
I have a feeling that this deviates from the intended design pattern of the Hotwire framework. I could probably encapsulate the extra javascript in a more generic slide_out_stream_listener_controller
or something to better conform, but I’m wondering if there’s an existing “Hotwire” way to do enable this flow.