The server can respond with HTML having the id="chat_room" hx-swap-oob="true" attributes which will tell htmx to swap out the #chat_room element with the new HTML.
The part I find most interesting is that there are no special requirements for the server at all. Not even for the websocket support. Any server which can reply with HTML will work.
Work on intercooler 2.0 (renamed to htmx) has begun. See htmx.org for more information!
It seems to be an improvement over Intercooler without any external dependencies and with fewer but stronger core concepts backed by a powerful extension system.
We at Bizneo have been using Intercooler.js for multiple years now. It has been really stable and a joy to work with. Our backend responds with HTML and Intercooler picks and replaces the selected elements in the page.
We want to make a few changes in the README and documentation before pushing the package to hex.pm, but it can be already used by fetching it from GitHub. We have been using it for some time without any problem.
# In your mix.exs
{:intercooler, "~> 0.1", github: "bizneo/intercooler"},
Looking at the similarity between HTMx and Intercooler.js, and since both come from the same author I will probably try to update the plug to support both libraries instead of Intecoooer only.
Is there a way to use HTMX with Phoenix and websocket, without using LiveView. Maybe with channels. Or do I have to code a basic websocket server into Phoenix for this ?
Phoenix web sockets work with channels and htmx likes to work with websockets without channels.
I have had a great experience using Server Sent Events (SSE) instead of web sockets. It works really nice with phoenix and htmx.
It can be barebones at time compared to other solutions (i.e. LiveView / Turbo)
You’ll want to rewrite 302s to 303s to avoid browser issues when implementing DELETE. Another option is to set the HX-Redirect header when it is a 302(?), which I have not tried. Here is more context. Hotwired/Turbo does the same thing. To make the mental model easier (even if Not Proper™) I just rewrite all 302s to 303s when sent to the browser so I don’t have to reason about whether or not it’s the proper response status. This will affect your browser tests though, so it would be worth looking into the HX-Redirect alternative:
defmodule HTMXRedirect do
import Plug.Conn
def init(default), do: default
def call(conn, _opts) do
register_before_send(conn, fn conn ->
if conn.status == 302 do
put_status(conn, :see_other)
else
conn
end
end)
end
end
Some issues I’ve ran into:
Scroll position is not properly restored when the current page you’re on doesn’t have the same height as the previous page.
Sometimes dynamically loaded scripts in the body do not load. I just disable hx-boost to those pages.
Overall, it’s fine.
It’s rough around the edges, maybe optimized for Django? No clue.
I like how everything is an attribute, while in Turbo you have to create custom elements and massage your markup differently.
Being able to html-swap different parts of the screen helps (flashes, for example)
I did have to reinvent the wheel for other things, like asset digest mismatch (i.e. turbo-track-reload).
As another alternative, I might suggest you checkout out live-templates, it’s a similar html first idea but connects to a stateful phoenix channel on the backend. It’s designed to be in an option if, for whatever reason, the front end html isn’t going to be served by Elixir. If your all in on Elixir already, LiveView is a great option.
I would disagree to it. HTMX’s predecessor intercoolerjs is a lot older than Liveview.
So i don’t think its gonna disappear in some time.
There are many libraries with HTML over the wire idea like - Turbo, Unpoly, AlpineAjax etc.
I have used htmx and turbo for more than 2 years and liveview for around 4. My experience using them is as follows-
htmx:
Follows the http protocol and the server needs to return html that would get inserted in the right place.
Since it follows the http protocol you would need to create a lot of routes for calling server actions
Need to be mindful of updating multiple places in the same page. There is a probability of missing things if you are not careful (although such scenarios are less frequent).
Performance is slightly less than liveview but its not noticeable to the end users (non technical)
JS integration is easier than with liveview - no hooks are needed (but we need to be a little mindful about reloads).
No state on the server side, all state is in the client or the url
If you have simple pages (for ex a static website) just putting hx-boost would make it a lost snappier.
Liveview:
Based on web sockets
The client and the server become one and the network gap dissolves so we can call the server functions from client without defining additional routes.
No need to return html fragments, liveview would automatically figure out what to send based on state changes. This is advantageous especially when multiple places in the page needs to be updated. No extra care is required.
Allows better locality of behavior for html and code as they can be in the same file. But inferior locality of behaviour for JS as it needs to be in hooks in a separate file.
JS integration via hooks - slightly more complex than using vanilla js as we need to be mindful of liveview life cycle events. But you get used to it pretty soon.
If you have simple static pages - liveview is not a good fit.
There is really only one difference between LiveView and HTMX: LiveView is stateful and HTMX is not. Everything else (like the much more thorough list above) is directly downstream of that.
Honestly the differences between what LiveView is (a stateful app on the server patching a thin client) and what HTMX is (stateless XHR into DOM) are substantial enough that I don’t really see how they can be compared at all. This is not to say that one is better than the other - they just do completely different things. The programming model is wildly different, and so are the use cases.
The only other thing to note is that what LiveView does is really only possible on the BEAM, as it can actually handle that many stateful connections without catching fire. The HTMX approach on the other hand is something you can do on any stack (including Phoenix!). But again, they are completely different approaches that are not useful for solving the same problems.
From what I understand, they are both promoted as covering most of the use cases. I understand they use different approaches but it’s not clear to me why they are “not useful for solving the same problems”