bigskysoftware / htmx

</> htmx - high power tools for HTML
https://htmx.org
Other
37.39k stars 1.26k forks source link

How to use the history to cancel a state? #907

Closed ddahan closed 2 years ago

ddahan commented 2 years ago

I'm trying tu build a simple form where the user can save the form or cancel it. It works lithe that:

1) Click on the button:

image

2) When the button is clicked, using an htmx call, it is replaced by this HTML fragment:

image

I'm trying to deal with the "Cancel" action. I just want to go back to the previous state the easiest possible way, when the user clicks on it.

In the official examples, when the cancel button is clicked, an AJAX call is made to get the data back. I don't like it because: 1) it makes an unnecessary AJAX call 2) in my case, I have no data to load, just the button UI. Following this pattern would force me to create a controller just to return the button itself, I guess it's overkill.

That's why, as a second thought, I was thinking of using the history to deal with this:

At first, it seems to work as expected. But there's something wrong: since I deal with history, the url has changed when I clicked on "New User": now the browser uses the url called to load my HTML fragment. So, if a make a refresh on this specific URL, I get my raw HTML fragment (not my whole page, with all the CSS)

image

I saw HTMX doc warned me about that:

If you push a URL into the history, you must be able to navigate to that URL and get a full page back! A user could copy and paste the URL into an email, or new tab.

I don't understand what's the right pattern to deal with this. My URL can not load an HTML fragment and the full page at the same time. Thanks for your help.

gone commented 2 years ago

One option with the hx-push-url strategy would be the check the incoming request if it's an htmx request or not. HTMX requests will have a set of headers identifying them as such, so you can make a controller call about if you need to render a full page or fragment.

a django focused example of that pattern would be https://django-htmx.readthedocs.io/en/latest/tips.html#partial-rendering

1cg commented 2 years ago

the htmx way would be to issue a request to restore the button

@gone's suggestion of reusing an existing end point is probably what I would do.

that said, there is no shame in squirreling that html away client side and restoring it via scripting, using VanillaJS, AlpineJS or, if you are brave, hyperscript. It's just a matter of restoring the content and calling htmx.process() on it.

ddahan commented 2 years ago

Thanks for the hyperscript idea. May I ask a simple code example of this? It's not very clear for me how to do it. Plus, I just found out this extension. It seems it's exactly what I need. But again, I'm lacking of full examples demonstrating how to do it. I have too many possibilities, it's pretty confusing.