htmx Tutorial · User Feedback · Lesson 12 of 30
Confirming Actions: hx-confirm and hx-prompt
Ask before destructive requests with hx-confirm, ask for a value with hx-prompt, and where custom dialogs fit in.
hx-confirm
hx-confirm="message" shows the browser's confirmation dialog before sending the request. If the user cancels,
nothing is sent:
<p id="file">report-2026.pdf
<button hx-delete="/files/report-2026.pdf" hx-confirm="Delete report-2026.pdf? This can't be undone."
hx-target="#file" hx-swap="outerHTML">Delete</button></p>
<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
server.delete("/files/:name", (req) => `<p><em>${server.escape(req.params.name)} was deleted.</em></p>`);
</script>
Like most attributes it's inherited, so one hx-confirm on a table can protect every delete button inside.
hx-prompt
hx-prompt="question" asks the user to type something. The answer is sent to the server in the HX-Prompt
request header:
<button hx-post="/rename" hx-prompt="New name for the project?" hx-target="#name">Rename project</button>
<h3 id="name">Untitled project</h3>
<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
server.post("/rename", (req) => server.escape(req.headers["hx-prompt"] || "Untitled project"));
</script>
Nicer dialogs
The native dialogs work everywhere but can't be styled. To use your own dialog, listen for the htmx:confirm
event, call event.preventDefault(), show your dialog, then call event.detail.issueRequest() when the user agrees.
Always keep server-side protection too: a confirmation is a convenience, not security.
Test yourself
Where does htmx put the text the user typed into an hx-prompt dialog?
In the HX-Prompt request headerIn a form field called promptIn the URL hashIn localStorage
Show answer
Answer: In the HX-Prompt request header
The server reads the HX-Prompt header.