nymanjon
I've found that to really reduce the complexity of my applications. If I really do need something more powerful with state machine interaction, then I use VanJS. But, really, I've only used that for my static sites where I need a little interaction on the front end and no back end connection.
Here's an example of using HTMZ-BE (which can easily be extended to HTMX 4.0 and Data-Star - if you need even more features).
https://github.com/jon49/Soccer
It also uses an _<action> attribute pattern on the HTML for simple, declarative front end state interaction. Makes the user's life a little nicer.
It's amazing how simple things can be if you work with it and think about, "I want simplicity." A lot of the front end frameworks add a lot of complexity, even nice frameworks like Svelte, I think because the paradigm is just wrong.
https://github.com/jon49/htmz-be
It's amazing how much further you can go when you flip the server as the one deciding where what should be updated on the page.
This was originally conceived by datastar and nomini also implements it this way. And HTMX 4.0 will have this as a first class citizen.
Also, morphdom/idiomorph get you a long way even when you have highly interactive pages, especially if you have to hit the back end anyways. If you don't need to hit the back end then a front end lib is fine. But even then, the simpler pattern of hypermedia-driven applications can be better.
See https://github.com/jon49/Soccer as an example of this.
I find React to be really complex. What normally takes me just some HTML rendered from the back end and some interactivity on the front end can be done in just a few lines of code, but React takes 10s of lines of code for what I can write in a single line of code using vanilla js. The virtual dom causes it to make everything state. I always find it odd that people reach for that as their front end. I could understand something like Svelte, but even that is too complex for my needs. But I'm always writing CRUD apps, so there is some complexity but not that much, React just makes something that was simple, super complex.
Here's the most complex app I've made with it. The most complex part of the app is the match page. I just use morphdom for that part of the app and it makes it super easy, I just send the whole main part of the page back and let a dom diff happen.
I also added a question for my soccer app. Cloudflare doesn't know how to work with service worker-driven applications :-) This one puts the back end in the service worker and uses HTMZ-BE to make it feel like you are using an app. So, basically, a front end MPA with nice interactivity. Super light weight for what it does and easy to use.[2]
<a id="contact1" href="/contact/1/edit" role="button">Edit</a>
Hhhmmm..., that's more verbose than both :-(
Here's an offline-first soccer app: https://github.com/jon49/Soccer
And here's an MPA that caches the pages and save the updates for later when you are back online. So, you can navigate around and see the old data even if you are offline: https://github.com/jon49/cash
Datastar's model of doing it this way really simplifies the front end even more compared to HTMX's model of having the elements on the front end decide where to put the returned HTML.
Back-end driven HTMZ development
https://jon49.github.io/htmz-be/
I replaced my `html-form` library with this as it has a smaller foot print and, therefore, easier to maintain.
HTML-form an Htmx-like library
This library takes an HTML-standards-first take to hypertext programming. Because of this it makes it easy to build progressively enhanced MPAs.
I've successfully built offline-first applications with it using service workers.
I recently did a rewrite (inspired by fixi) cleaning the code up and making it tinier and moving parts to extensions.
I've been programming on personal projects with html-form (my own lib that is a radically paired down version of HTMX with a focus on using native form controls, which makes it so you don't need hydration like you do in HTMX).
So, some thoughts on your problem.
One note. Many people mention OOB. But there is also hx-select, which can be quite handy.
I think there are multiple different approaches that are possible, that I can think of, depending on your needs.
Use eventing. On the server create an event that will be called on the front end by HTMX. When this is called have some vanilla JS that updates the class on your location in the form.
Send all the forms down and have them only visible based on CSS or using an input element is checked or not or using JS. That would be pretty straight forward.
If the form passes then replace all the body contents or main element. If it doesn't just update the form and add any user information. Or send an event back which causes a popup to tell the user what their issue is. Or send an even that causes some text to show.
Also, you can also use CSS and native HTML form validation that will show text underneath an input (or above the input) that tells the user what the the input requires. Modern CSS has a pseudo selector which only turns on when the input is invalid[1].
This is simple enough that a straight up MPA could be used with page animations between pages using view transitions[2].
Similar to one of the solutions above, but using data-action style of programming.[3]
But, I usually try to not over complicate things.
[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/:user-inval...
[2]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_view_tr...
I do like front end libs. I use them sometimes for the right context. But all the business apps I've worked on have never needed a front end lib. With web components even less so than before as the state based interactions that are local to that input element or some other element doesn't need a full blown framework.
My favorite front end lib right now is VanJS. It feels like writing straight vanilla JS without the cruft of writing actual vanilla JS. HTMX is good too, if you are working with back end state but need a little more smooth interaction. Of course, Datastar, html-form, etc all work too.