Improved documentation for htmx:confirm event and examples for implementing sweetalert (#2926)

* Add detail.question and detail.issueRequest(skipConfirmation=false) documentation to htmx:confirm event

* Update htmx:confirm event documentation

* Update htmx:confirm event documentation

* Update htmx:confirm event documentation

* Modify htmx:confirm event documentation
This commit is contained in:
Luis Eduardo 2024-09-25 01:39:28 -06:00 committed by GitHub
parent 44c4de41cc
commit 27b5bcc438
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 63 additions and 24 deletions

View File

@ -179,43 +179,70 @@ than a single value.
### Event - `htmx:confirm` {#htmx:confirm} ### Event - `htmx:confirm` {#htmx:confirm}
This event is triggered immediately after a trigger occurs on an element. It allows you to cancel (or delay) issuing This event is fired on every trigger for a request (not just on elements that have a hx-confirm attribute).
the AJAX request. If you call `preventDefault()` on the event, it will not issue the given request. The `detail` It allows you to cancel (or delay) issuing the AJAX request.
object contains a function, `evt.detail.issueRequest()`, that can be used to issue the actual AJAX request at a If you call `preventDefault()` on the event, it will not issue the given request.
later point. Combining these two features allows you to create an asynchronous confirmation dialog. The `detail` object contains a function, `evt.detail.issueRequest(skipConfirmation=false)`, that can be used to issue the actual AJAX request at a later point.
Combining these two features allows you to create an asynchronous confirmation dialog.
Here is an example using [sweet alert](https://sweetalert.js.org/guides/) on any element with a `confirm-with-sweet-alert='true'` attribute on it: Here is a basic example that shows the basic usage of the `htmx:confirm` event without altering the default behavior:
```javascript ```javascript
document.body.addEventListener('htmx:confirm', function(evt) { document.body.addEventListener('htmx:confirm', function(evt) {
if (evt.target.matches("[confirm-with-sweet-alert='true']")) { // 0. To modify the behavior only for elements with the hx-confirm attribute,
evt.preventDefault(); // check if evt.detail.target.hasAttribute('hx-confirm')
swal({
title: "Are you sure?", // 1. Prevent the default behavior (this will prevent the request from being issued)
text: "Are you sure you are sure?", evt.preventDefault();
icon: "warning",
buttons: true, // 2. Do your own logic here
dangerMode: true, console.log(evt.detail)
}).then((confirmed) => {
if (confirmed) { // 3. Manually issue the request when you are ready
evt.detail.issueRequest(); evt.detail.issueRequest(); // or evt.detail.issueRequest(true) to skip the built-in window.confirm()
} });
}); ```
}
And here is an example using [sweet alert](https://sweetalert.js.org/guides/) on any element with a `confirm-with-sweet-alert="{question}"` attribute on it:
```javascript
document.body.addEventListener('htmx:confirm', function(evt) {
// 1. The requirement to show the sweet alert is that the element has a confirm-with-sweet-alert
// attribute on it, if it doesn't we can return early and let the default behavior happen
if (!evt.detail.target.hasAttribute('confirm-with-sweet-alert')) return
// 2. Get the question from the attribute
const question = evt.detail.target.getAttribute('confirm-with-sweet-alert');
// 3. Prevent the default behavior (this will prevent the request from being issued)
evt.preventDefault();
// 4. Show the sweet alert
swal({
title: "Are you sure?",
text: question || "Are you sure you want to continue?",
icon: "warning",
buttons: true,
dangerMode: true,
}).then((confirmed) => {
if (confirmed) {
// 5. If the user confirms, we can manually issue the request
evt.detail.issueRequest(true); // true to skip the built-in window.confirm()
}
});
}); });
``` ```
##### Details ##### Details
{target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest}
* `detail.elt` - the element in question * `detail.elt` - the element in question
* `detail.etc` - additional request information (mostly unused) * `detail.etc` - additional request information (mostly unused)
* `detail.issueRequest` - a no argument function that can be invoked to issue the request (should be paired with `evt.preventDefault()`!) * `detail.issueRequest(skipConfirmation=false)` - a function that can be invoked to issue the request (should be paired with `evt.preventDefault()`!), if skipConfirmation is `true` the original `window.confirm()` is not executed
* `detail.path` - the path of the request * `detail.path` - the path of the request
* `detail.target` - the target of the request * `detail.target` - the element that triggered the request
* `detail.triggeringEvent` - the original event that triggered this request * `detail.triggeringEvent` - the original event that triggered this request
* `detail.verb` - the verb of the request (e.g. `GET`) * `detail.verb` - the verb of the request (e.g. `GET`)
* `detail.question` - the question passed to `hx-confirm` attribute (only available if `hx-confirm` attribute is present)
### Event - `htmx:historyCacheError` {#htmx:historyCacheError} ### Event - `htmx:historyCacheError` {#htmx:historyCacheError}

View File

@ -36,12 +36,22 @@ which is then picked up by `hx-trigger`.
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script> <script>
document.addEventListener("htmx:confirm", function(e) { document.addEventListener("htmx:confirm", function(e) {
// The event is triggered on every trigger for a request, so we need to check if the element
// that triggered the request has a hx-confirm attribute, if not we can return early and let
// the default behavior happen
if (!evt.detail.target.hasAttribute('hx-confirm')) return
// This will prevent the request from being issued to later manually issue it
e.preventDefault() e.preventDefault()
Swal.fire({ Swal.fire({
title: "Proceed?", title: "Proceed?",
text: `I ask you... ${e.detail.question}` text: `I ask you... ${e.detail.question}`
}).then(function(result) { }).then(function(result) {
if(result.isConfirmed) e.detail.issueRequest(true) // use true to skip window.confirm if (result.isConfirmed) {
// If the user confirms, we manually issue the request
e.detail.issueRequest(true); // true to skip the built-in window.confirm()
}
}) })
}) })
</script> </script>
@ -62,3 +72,5 @@ when the question depends on the element e.g. a django list:
<button hx-post="/delete/{{client.pk}}" hx-confirm="Delete {{client.name}}??">Delete</button> <button hx-post="/delete/{{client.pk}}" hx-confirm="Delete {{client.name}}??">Delete</button>
{% endfor %} {% endfor %}
``` ```
Learn more about the [`htmx:confirm`](@/events.md#htmx:confirm) event [here](@/events.md#htmx:confirm).