Custom `hx-prompt` dialogs.
While I've had great success creating custom hx-confirm dialogs, the same can not be said for hx-prompt. I'd like to prompt the user for their password before deleting their account, but prompt() shows the password.
It seems that, (unlike hx-request) the handler for hx-prompt is hard-coded to call prompt(), you can't pre-fill the data.
Is there a way this could be avoided such that hx-confirm and hx-prompt function in the same way?
hx-prompt
https://github.com/bigskysoftware/htmx/blob/03c3af724cb5156e932d7b47c3e3fa58e1c5ff59/src/htmx.js#L4383-L4393
hx-confirm
https://github.com/bigskysoftware/htmx/blob/03c3af724cb5156e932d7b47c3e3fa58e1c5ff59/src/htmx.js#L4231-L4240 https://github.com/bigskysoftware/htmx/blob/03c3af724cb5156e932d7b47c3e3fa58e1c5ff59/src/htmx.js#L4288-L4299 https://github.com/bigskysoftware/htmx/blob/03c3af724cb5156e932d7b47c3e3fa58e1c5ff59/src/htmx.js#L4395-L4401
It seems that it could be as simple as changing the type of confirmed from boolean to string|false. I was able to do this with very little effort:
https://github.com/sbrow/htmx/commit/680082a5953c062787a93a4bb03f3614f35021b9
I think this could be a breaking change for existing hx-confirm use cases. This seems like a whole new feature to me and ideally should first be implemented by writing your own htmx extension or implementing the feature using event listeners. You already need to use event listeners on the confirm event to make use of this change anyway so adding a second event listener on configRequest could be all it would take to add the required hx-prompt header to the final request based on data retained during the manual confirmation stage. wrapping both events into a single htmx extension to make it more declarative could make sense as well
I wasn't aware of the configRequest event, I'll see if I can make it work with that. However, since all arguments currently get converted to a boolean value anyway, we can easily preserve that behavior.
How it works now:
issueRequest('some string') -> confirmed = true
issueRequest(true) -> confirmed = true
issueRequest(1) -> confirmed = true
issueRequest(false) -> confirmed = false
issueRequest('') -> confirmed = false
The only change that needs to be made is when a non empty string is passed
issueRequest('some string') -> confirmed = 'some string'
It still evaluates to a truthy value and behaves the same way as expected.
yeah the only documented examples from https://htmx.org/events/#htmx:confirm are issueRequest() and issueRequest(true) and the first one passes in undefined in your suggested change which creates an infinite loop as confirmed === undefined re-fires the htmx:confirm again as it is currently designed.
There are likely to be many ways to adjust the final request to include the confirmation content via either htmx:configRequest handler but there is the issue that you need to store the data somewhere between the JS code in the htmx:confirm handler and the configRequest one. It is also possible to simply modify the event.target element to have additional htmx attributes like hx-headers or hx-vals which will change the request that it will make when you re issueRequest() it.
Also note that hx-prompt just sets a clear text header value and I don't think it is secure to send user passwords in clear text in headers as these are not designed for sensitive use cases and will often be left in logs etc. You may also want to random salt and hash the password string before you send it to avoid password decoding or rainbow table lookups. Also note that hx-get and hx-delete send data in the url parameters which is not a good place to put passwords either as ideally the body should be used where possible.
Thank you for pointing out the flaw in my logic. Silly me thought I was so clever coming up with a solution, I failed to do my due diligence 😢. I'll try to reign in my ego for the rest of this thread.
I based my solution on the hx-confirm solution from the official confirm examples on htmx.org.
It feels idiomatic to me to leave the html untouched, i.e. do all the custom stuff in JS land, so my confirm dialogs have a simple hx-confirm="the yes/no question" attr on them, the prompts have hx-prompt="the question with a string answer", and the modal itself has js that intercepts the events.
I appreciate that htmx makes it easy to capture the confirm event and handle it yourself, and I was suprised to see that hx-prompt disallowed you from doing the same thing.
I will look at the proposed htmx:configRequest solution, but it looks like that code would be a harder to follow in however many years it will be before I have to look at this code again xD
The code as written in #3377 does cause an infinite loop instead of falling back to the native dialogs as HTMX currently does. Should I bother looking for a way around that, or just close the PR? Or put another way, is this something the htmx team see as an issue?
Thank you for making the world of web development a smoother place 😎
Should I close this issue and corresponding PR?