Premise
Sometimes (not always) the simplest solution to a problem is also the most straightforward one. Suppose we have the following problem:
- a textarea that should accept markdown
- a preview area that should show the rendered markdown as you type
- changes are automatically saved.
As it turns out, you can solve all three issues with a single Turbo Frame wrapping a form.
Starting Point
In our markup, we have a simple form containing a <textarea>. That form itself is wrapped by a Turbo Frame:
https://stackblitz.com/edit/turbo-frames-markdown-preview?file=index.html%3AL41-L41
Note that below the form there’s an <article> tag containing a {content} placeholder to be filled with the rendered markdown on the server.
Speaking of, we are mimicking a “template engine” again in the GET route, simply replacing this placeholder by the string held in a local content variable. The equivalent in Rails would be an instance variable, or simply an attribute on a model.
https://stackblitz.com/edit/turbo-frames-markdown-preview?file=index.js%3AL18
Whenever the form is submitted, we transform the markdown into HTML markup using the marked package (the equivalent in Ruby-land would be kramdown, for example):
https://stackblitz.com/edit/turbo-frames-markdown-preview?file=index.js%3AL28
The result is then stored in the mentioned content variable, and a 303 response is issued to redirect back to /.
Challenge
To render a preview, it’s just necessary to submit the form. Write an event listener that triggers a POST request and reloads the frame:
This is what the result looks like:

If you’re curious as to why a <turbo-frame> is even needed, try to comment it out in the HTML. What do you observe?
Teaser
Triggering a server roundtrip for every keystroke might not be feasible. What could you do to remedy this?
 
         
   
        

