I have used htmx before and want to test Turbo now. I think my mindset is still rooted in htmx, which is way Turbo is not working for me and I need some help.
In htmx if I want to swap a page element, I respond to a frontend request with just the new element and the id of what to replace, nothing more i.e. not a full page. I’m trying to achieve the same behavior with Turbo but failing. I’ve seen people describe using Streams (e.g. Form does not update turbo-frame - #2 by remast) in the way I want.
I’m sending a POST request with a form (which is not inside a turbo frame, as per the post above):
text/vnd.turbo-stream.html is not in the accept headers (Turbo Handbook says it should)
I respond with (see below) and add the MIME type from the previous point
Seems like the turbo library might not be loaded. If you put a hyperlink on the page, does a click result in a fetch request? (it should with Turbo working)
which is not what I expected. Now I’m importing turbo correctly and I see fetch requests when I click on links, but responding with the stream in the original post results in the same white screen (I still don’t see text/vnd.turbo-stream.html in the headers)
respond with a stream partial containing a frame and src (spinner)
respond to 2. with the data
very nice, this way I’m not keeping track of any state.
I’ll try requestSubmit() with another browser, I was using submit() because Safari doesn’t support the requestSubmit() and I really wanted to have no button in this form
Glad to see that there was some help and this was figured out. As someone who uses Clojure whenever I can, I’d be interested in hearing at some point how your experience using Hotwire with a Clojure backend (or with Clojurescript) so if you ever have the time please post an experience report from your test.
No problem! I don’t know Javascript at all, so using things like htmx and turbo lets me be as fast as (or faster) than my colleagues worrying about the latest JS framework. I’ll write it up once I have time. It’s a smooth experience.
@tleish one last question about htmx vs turbo. I was relying a lot on htmx’s hx-swap-oob to “piggyback” multiple updates on a single request e.g. swapping multiple elements for spinners and then again with the final results. To achieve this with Turbo my understanding is I’ll have to setup websockets. Is that correct?
Assuming you are referring to turbo-streams, they are not exclusive to websockets. turbo-streams can be used with http requests or websockets, depending on the need. If you want to update users DOM elements as part of an HTTP request, just return HTML with turbo-stream element(s). If you want to update users DOM outside an HTTP request (delated job, another user updated data, etc), then you must use websockets with turbo-stream element(s).
<turbo-stream action="replace" targets="some_id">
<template>
<!-- Some new element !-->
</template>
</turbo-stream>
<turbo-stream action="replace" targets="some_other_id">
<template>
<!-- Some other new element !-->
</template>
</turbo-stream>
it will update both targets? the documentation is a bit ambiguous in regards to this?
My use-case is to update two tables far away from each other after a single user action.
It does not make sense to use targets for a single id (e.g. targets='#some_id'), use target instead
Multiple turbo-streams
You can include multiple turbo-streams in a single response. Turbo will process each one of them.
<turbo-stream action="replace" target="some_id">
<template>
<!-- Some new element -->
</template>
</turbo-stream>
<turbo-stream action="after" target="some_other_id">
<template>
<!-- another new element -->
</template>
</turbo-stream>
<turbo-stream action="replace" targets="[data-value='foo']">
<template>
<!-- shared content between multiple elements -->
</template>
</turbo-stream>