4 ms·
So, I have only been working in htmx for about a week on a multi step checkout app, and while it's been mostly awesome, I think I ran into the Achilles heel of
by ledgerdev 5y ago
So, I have only been working in htmx for about a week on a multi step checkout app, and while it's been mostly awesome, I think I ran into the Achilles heel of htmx, form state and the back button.
In short of you enter data into a form then htmx push navigate away, when you click the browser back button you get the dom as it was originally delivered from the server, without any data the user might have entered into text boxes. This is a show stopper problem and been working on work arounds, not sure any is good. Basically we have resorted to plain old full page reloads with client side redirect to resolve this.
- polyrand 5y agoThe thing about HTMX is that the mental model about state should tend towards "the server is aware of everything". With the added benefit that you can achieve better RESTful URLs that respect the navigation actions. Without having tried this (but having used HTMX quite a lot), I would try the following (let me know if I didn't understand the problem correctly): Checkout has the following URLs, one for each step: * page.com/checkout (optionally with ?step=0) * page.com/checkout?step=1 * page.com/checkout?step=2 * page.com/checkout?step=3 Now you need 2 things: 1) Making sure the server knows how to render all those pages independently (like if the user does a hard-refresh or if they open that URL directly, without navigating to it through a link). Note: I believe this should be the default in any website if you respect the concept of a URL (whether client or server-side rendered). 2) If there's a form input at each step, the server needs to store that info and be aware that the user has an incomplete checkout. Now the user is at step=2 and presses the back button, or clicks on the step=1 link. In that case, the server should know the information stored in the point no. 2 above, and return an HTML form with the data pre-filled based on the last state. E.g: <input type="text" id="name" name="name" value="Foobar"> I think there are 3 main keys: 1. You need different URLs for each step. 2. Each URL should work both with HTMX (maybe using hx-push-url or the HX-Push header) and *without*. That is, any navigation to that page should also render the same HTML. 3. The server needs to be aware of the state. When a user requests page.com/checkout?step=2, the server should know if the HTML form requires pre-filled values. This increases a bit the complexity on the server, but I believe it reduces the client-side complexity a lot more.
- ledgerdev 5y ago> 2) If there's a form input at each step, the server needs to store that info and be aware that the user has an incomplete checkout. Now the user is at step=2 and presses the back button, or clicks on the step=1 link. In that case, the server should know the information stored in the point no. 2 above, and return an HTML form with the data pre-filled based on the last state. The problem is that when you press back button in the browser, it doesn't make another request to the server. It reloads the page from browser memory. A link back can be made to work, but that's not what I was speaking to. I tested the most trivial case, when you return a response, and push navigate to next step, then press browser back button, form state is not retained. Both chrome and firefox do not restore the form state on navigation back after a url push navigation. I don't think that without some client side JS that saves/reloads prior form state this is a solvable problem because of browser behavior. Either that, or perhaps use different divs for each step then have js hide/show them which is what I will try next but involves writing js to do so. EDIT: tried multiple divs on same page, same behavior so that will not work. It's pretty clear that htmx hasn't considered back button much at all, it also clobbers the page titles in history as well (https://github.com/bigskysoftware/htmx/issues/746 https://github.com/bigskysoftware/htmx/issues/746), but that's a fixable problem.
- polyrand 5y agoI see... What about using hx-trigger="load" for the form? Maybe that makes the browser reload it even after hitting the back button? (Sorry I can't check this right now, just a random idea). Edit: I quickly tried it (mixing hx-from="#some-other-element" and hx-trigger="revealed", and it seems to be doing the request, but I haven't looked a lot.
- ledgerdev 5y agoOk, so turns out default chrome/firefox on windows/android were not issuing the history refresh request on back button click. Turns out you need to add some additional config to make that happen. It's now working, and it's excellent. Set htmx to not cache prior pages by setting `htmx.config.historyCacheSize = 0` in window.onload. Also set the http caching header `cache-control: no-cache`
- delbronski 5y agoOne approach you can try is using the localStoeage API to temporarily store the form data of the user. I have done something similar in the past. You can use a light library like Alpine JS to make this work nicely. When the form renders, check if there is any temporary form data in localStorage, if so initialize the form with that. When the user saves the form remember to clear localStorage. This works nicely because even if the user closes the browser or something by mistake it is all there, and you don't need to keep temporary data around in your database.