Turbo frame not replaced when at root of an HTML fragment
See original GitHub issueFirst, I am using this version of Turbo from the CDN.
https://unpkg.com/@hotwired/turbo@7.1.0/dist/turbo.es2017-umd.js
Let’s say I have a basic form within a frame with only a submit button.
<h1>Turbo Frame example</h1>
<turbo-frame id="results">
<p>Use the following button to replace the frame</p>
<form action="/turbo/search" method="post">
<input type="submit" value="swap">
</form>
</turbo-frame>
When I click the button, the POST
request is made to /turbo/search
. In the response from the server, I return a fragment of HTML (without any layout or anything) containing a h1
followed by the matching frame. Everything is ok so far and the initial frame gets replaced.
Response is:
<h1>Full list of results</h1>
<turbo-frame id="results">
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
</turbo-frame>
And Turbo changes the page to:
<h1>Turbo Frame example</h1>
<turbo-frame id="results">
<ul>
<li>first</li>
<li>second</li>
<li>third</li>
</ul>
</turbo-frame>
Now, if I decide to remove the h1
and only return the frame as the response, it does not get swapped. Nothing happens, and I don’t have any message in the console. It feels like Turbo does not know how to extract the frame from the response if this response is the frame.
Am I doing something wrong or is it a known behavior? Thanks
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
This makes total sense. Sorry for opening an issue that isn’t one!
Thanks a lot for your exploration and for having found the root cause.
For reference and for those who use Go and fall into this issue, the package
net/http
in stdlib tries to detect the content type when not set explicitly.This is done in DetectContentType.
For “full” HTML documents, it works consistently. I also never had any issues when rendering partial HTML documents. But the problem here with Turbo is that
<turbo-frame>
isn’t recognized as a standard HTML tag, and this makes the detection fail.Hence the need to explicitly set
text/html
.Here is the fix in my example repo (I will keep it public in case anyone needs that). I also published the fix under a release
v0.0.2
.https://github.com/lobre/go-turbo-frame/commit/6b42ae553d12338dd7a7978f1fce66cb5ebc2b97
Sorry I haven’t given those details. It returns a 303 redirect to
/turbo/results
(which gets executed by the browser and succeeds with a 200). And this result page is the one returning the fragment (which is what I should be doing of what I see in the docs). And again, it works perfectly if I add anything outside the frame in the returned HTML fragment.I have also just tested with an anchor (
<a>
) instead of a form, and I have the same behavior. The server directly returns a 200 with the fragment but the frame won’t swap if the result only contains the matching frame.In both of those cases, I never use Streams. I don’t return any, and I don’t set
text/vnd.turbo-stream.html
on the response.