I've found Htmx to be smug and misleading. "Look how simple it is! No JavaScript! Ignore the fact that you need a complex backend in a separate language and environment to generate your html."
Separate language is fine for those of us willing to write anything but JS. As long as it means writing less JS, a separate backend isn’t that big of a deal.
There's nothing philosophically or aesthetically good about
<button hx-get="/confirmed"
hx-trigger='confirmed'
onClick="Swal.fire({title: 'Confirm', text:'Do you want to continue?'}).then((result)=>{
if(result.isConfirmed){
htmx.trigger(this, 'confirmed');
}
})">
Click Me
</button>
or about
<div hx-get="/clicked" hx-trigger="click[ctrlKey]">
Control Click Me
</div>
or
<form id="example-form" hx-post="/test">
<input name="example"
onkeyup="this.setCustomValidity('') // reset the validation on keyup"
hx-on:htmx:validation:validate="if(this.value != 'foo') {
this.setCustomValidity('Please enter the value foo') // set the validation error
htmx.find('#example-form').reportValidity() // report the issue
}">
</form>
Htmx's own examples push you to code that is unorganized and inaccessible.
In two of those three examples, the entirety of the disorganization and inaccessibility comes from the Javascript shoved into them.
In the remaining example, IMO it looks about as organized and accessible as I can imagine as far as HTML goes - my one complaint being the use of a div instead of something more semantically meaningful.
Ironically I can read through this code and know exactly what it does with no other context. I don’t even know what swal is but I can still tell what it does.
Sorry was typing that on my phone so got lazy, `doThing` would be a method/function of some sort. You can also write it inline if you so wish, like `@click="console.log('hello')"`
Any non-standard HTML attributes look cursed to me, it seems like HTMX claims to be a solution for JavaScript excessive complexity but at the same time creating complexity in another place where is doesn't belong. There is a reason not XML but imperative C-like syntax stuck around for doing procedural things on the web
I feel like there is a middle ground which is being excluded. I'm leaning towards alpine.js or similar lightweight JS frameworks which have better ergonomics than react or plain JS. Webcomponents also without Vue or React are a nice solution.
Oh definitely - I'm not an absolutist. I just want to have the least amount of contact with those aspects of the Javascript ecosystem that take me further away from HTML over HTTP and progressive enhancement.
And I fully accept that "web apps" probably need complex frameworks. I just think most people aren't really building web apps - they are building web sites.
Dunno where you got the first example from, but in idiomatic htmx it would be:
<button hx-get="/confirmed" hx-trigger="Do you want to continue?">Click Me</button>
Hardly the horror story you are trying to write.
The second example: really? The words 'get' and 'trigger' don't tell you what it's going to do?
> Htmx's own examples push you to code that is unorganized and inaccessible.
You realize these are demo, ie sample code right? No one is forcing you to write exactly that code? You can write organized and accessible code in your own project?
> htmx supports the hx-confirm attribute to provide a simple mechanism for confirming a user action. This uses the default confirm() function in javascript which, while trusty, may not be consistent with your applications UX....In this example we will see how to use sweetalert2 to implement a custom confirmation dialog.
It's implementing a custom confirmation dialog. Customized, non-default UI/UX usually means custom-written code in any framework I'm aware of. Maybe React has implemented magical customizations since the last time I checked.
React doesn’t require you to both abandon the principles of the library and write an inline string of code to run something slightly custom when you click a button.
htmx doesn't require you to write inline code in strings either, it's just a convenient compact way to do it in a demo. Also, it's not 'abandoning' any 'principles' because the 'principle' is to leverage small bits of JavaScript in a high-impact way. Eg, https://dev.to/yawaramin/handling-form-errors-in-htmx-3ncg
So where else will you put this code? A separate file? Multiple files? Maybe specific files for specific bits of UI? Maybe then you’ll need to handle bundling, transpiling, minification? Oops, we’re back to an evil pile of JS code that needs to be built.
Not really? HTTP/2 and ES Modules exist now, lol. And so does brotli compression done by my CDN. Bundling/transpiling/minification are basically obsolete technologies.
you can take anything in this type of context and it will look unorganized and inaccessible. react, angular, svelte, whatever-framework-du-jour … and much much worse than these examples
Why does it have to be a separate language? You can serve templates with javascript, thus it works just fine with HTMX. I think you have some fundamental misunderstanding.
> No JavaScript! Ignore the fact that you need a complex backend in a separate language
Backend in a language that isn't JavaScript is a feature.
Also, a backend where you just serve a template instead of full layout (server-side rendered app) or JSON (client-side rendered app) is not more complex in most of scenarios.
Nowhere does htmx say 'No JavaScript'. We say 'targeted, high-leverage use of JavaScript'. And neither do we say 'ignore' that you need a 'complex' backend (backends do complex work, they will be incidentally complex to a certain extent anyway). We say HOWL–Htmx On Whatever you Like. It works with any backend and language you prefer and that's strength. Believe it or not, people use languages other than JavaScript.
Except you bill yourself as a replacement for React, Next, etc. No more components! No more state! No more crazy logic or builds or code or maintenance! Just use htmx, everything becomes so simple!
None of that goes away, of course, it just moves to a different repo.
We don't bill htmx as a replacement for React or Next, only for the use cases that make sense for its capabilities, which often happen to be things people are using React and Next for because that's all they know.
Actually, duplication of state, routing logic, auth logic, etc. really do get eliminated. Because we're maintaining all that on the server-side only and not having to reproduce it on the client side. It's a huge win.
I don't need to keep track of it, because that state is embedded in the hypermedia ie HTML page itself. Eg, I implemented a pagination component in htmx. It has a 'prev' button, a page display, and a 'next' button. If I'm on page 1 and I press the 'next' button, then I have my backend server respond with the next page and also a re-rendered pagination component with all three elements now pointing at their new correct pages.
Except these aren't pages. They're slides in a carousel. There's no data to load. The markup isn't substantively changing. But instead of just translating an element, if a user clicks on the next button, we make an http request to a server, wait for the server to receive it, wait for it to generate a snippet of html, wait to get it back, and then drop it in. That's a pretty laggy UI. And as a result of that replacement, you lose the focused element and any possibility for animation.
What happens when you click quickly? Does the UI just freeze until it eventually loads... some slide? What if you want a touch carousel using scroll-snap? How do you destroy and replace the entire section without interrupting the user?
If you want to have a purely client-side carousel then this is outside the domain of htmx :shrug: You implement the carousel on the client-side. Use whatever library you like. Personally I think web components are a great complementary fit with htmx. But here you've just moved the goalpost. What you said earlier:
> No more state!...Just use htmx, everything becomes so simple!...None of that goes away, of course, it just moves to a different repo.
With a purely client-side component, the state is managed purely on the client side, and the server would not touch it anyway. So it didn't have duplication of state to begin with, and htmx is solving (among other things) the duplication of state problem. So again–this example is not relevant to htmx.