Premise
A recurring question that arises when dealing with Turbo Frames is how to apply changes to the DOM that are outside of the targeted frame. The most common example is updating the flash component that typically lies somewhere in the top part of your application layout.
Normally, there are two ways to achieve that:
- either break out of the Turbo Frame, i.e. promote to full page navigation,
- or if you want to target only the frame, for efficiency reasons, send a Turbo Stream
replace
action with the contents of the flash.
What bugs me about the latter is that there’s some implicit duplication here: Often, the server actually renders the whole template (including the flash), but only the targeted Turbo Frame is exchanged. We’ll explore a third way to leverage this without falling back to a full page visit.
Starting Point
We start with a very simple form again: A status updater. The template consists of a <turbo-frame id="form-wrapper">
, which in turn contains the status and a form to update it. Above this, we have two <span>
s containing the notice
and alert
flashes:
https://stackblitz.com/edit/turbo-frame-flash?file=index.html
On the server side, I’ve mimicked a Rails controller again. It sends a 303 response in the success case, and rerenders the form and sends a 422 in the failure case:
https://stackblitz.com/edit/turbo-frame-flash?file=index.js%3AL36
Note that this also means resetting the flashes to an empty string once they’ve been used.
Challenge
Your challenge is to take the FetchResponse
passed to the turbo:submit-end
event’s detail property, and use it to update the flash in our existing document
:
As usual, here’s a preview of the result, note that the dashed border indicates the wrapping Turbo Frame:
Caveat
You’ll have to create a template
element from JavaScript to place the HTML coming from the server in it, and discard it afterwards.