A few features which look minor but the author got totally right, which IMHO would allow this solution to scale very well with more complex applications.
generates an ajax request with this header by default:
```
X-Alpine-Target: comments comments_count
```
This is very very cool! In most usecases, one the serverside I can return a full html document and alpine-ajax will only look for #comments and #comments_count in the response. BUT, if I want the serverside to be faster (ie: do less), then the client is able to tell the server which parts of the html it wants via the `X-Alpine-Target` header -- instead of the server having to know which parts need updating via the url alone. It's like graphql for the htmx/hotwire architecture.
2) `ajax:missing`. If the client expects dom ids to be in the response and they aren't there, you can create a sentry error to expose the broken "contract" between the initial page's request and the action's response.
3) x-merge="append"
In hotwire, the html markup is dumb and the turbo-stream response is smart (`turbo-stream action="append"`). But in alpine-ajax, the response is dumb and the html markup is smart (`x-merge="append">`). This difference is subtle, but it allows for the serverside responses (for actions) be more general purpose/discrete components, while the ux which might change from page-to-page or section-to-section is decoupled to that page's/section's container html.
4) x-sync
"Elements with the x-sync attribute are updated whenever the server sends a matching element, even if the element isn't targeted with x-target."
Wow - amazing developer ux for cross cutting concerns like notifications, flash messages, etc. So practical.
5) Creating demos with an alpine-ajax mock server.... wow, an out of the box way to make standalone component test pages.
random idea: an event for "x-sync:missing". the server responds with `<ul x-sync id=notification>`, but the page doesn't have a matching id (and the notifications aren't inside a different target....). if the last part is slow to figure out, people could opt into it with "x-sync x-sync-required".
My first reaction was “why do I need an htmx-like version written in alpine?” when I could just use htmx. BUT… if you assume that you will need something more low level to complement htmx (“htmx + alpine” OR “htmx + hyperscipt”) and if you decide hyperscript is not for you, then it does make sense to a stack where the higher level is built upon the lower level: alpine-ajax + alpine.
Looks very interesting!
Also loved the comparisons, especially with rails/turbo and the downsides of custom elements wrt tables.
Yes! You’ve reminded me that there’s some subtle gotchas when using HTMX server-side that are probably worth documenting too. For one, HTMX starts with the assumption that you’re returning HTML fragments, but not all templating languages have good support for decomposing layouts into fragments. You can work around this using hx-select but Alpine AJAX works kind of like hx-select by default.
Also, there’s some response header juggling you have to do when submitting forms that have a validation step before redirecting: https://github.com/bigskysoftware/htmx/issues/369
I’ve tried to iron out any footguns or server requirements I’ve bumped into while using HTMX & Hotwire in my projects.
+1. I’m also using it and it’s truly refreshing after so many unnecessary SPAs. The latest generation of js meta frameworks made me switch and I’m so much happier with Livewire.
Yeah, Alpine components have `x-init` that works just like the load trigger. You can fire off an AJAX request inside that directive, there's an example here: https://alpine-ajax.js.org/examples/lazy-load/
Haha you’re not wrong. I love jQuery, but Alpine’s declarative style feels better, and since we don’t have to worry about all the backwards compat we get a library that’s half the size of jQuery Slim.
1) X-Alpine-Target
``` <form method="post" action="/comments" x-target="comments comments_count" ```
generates an ajax request with this header by default:
``` X-Alpine-Target: comments comments_count ```
This is very very cool! In most usecases, one the serverside I can return a full html document and alpine-ajax will only look for #comments and #comments_count in the response. BUT, if I want the serverside to be faster (ie: do less), then the client is able to tell the server which parts of the html it wants via the `X-Alpine-Target` header -- instead of the server having to know which parts need updating via the url alone. It's like graphql for the htmx/hotwire architecture.
2) `ajax:missing`. If the client expects dom ids to be in the response and they aren't there, you can create a sentry error to expose the broken "contract" between the initial page's request and the action's response.
3) x-merge="append"
In hotwire, the html markup is dumb and the turbo-stream response is smart (`turbo-stream action="append"`). But in alpine-ajax, the response is dumb and the html markup is smart (`x-merge="append">`). This difference is subtle, but it allows for the serverside responses (for actions) be more general purpose/discrete components, while the ux which might change from page-to-page or section-to-section is decoupled to that page's/section's container html.
4) x-sync
"Elements with the x-sync attribute are updated whenever the server sends a matching element, even if the element isn't targeted with x-target."
Wow - amazing developer ux for cross cutting concerns like notifications, flash messages, etc. So practical.
5) Creating demos with an alpine-ajax mock server.... wow, an out of the box way to make standalone component test pages.