summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorCarson Gross <carson@bigsky.software>2025-01-08 12:33:45 -0700
committerCarson Gross <carson@bigsky.software>2025-01-08 12:33:45 -0700
commitbc95b40004e249075314a119a0f3a1c3bdaed619 (patch)
treea26f89079bb6f000449af9a9bb8b7a63e11f9e13
parent69edc99956f2f3dd6e05fd189fdb93e5b12afcac (diff)
parent906299602552afddcd16cc384c0dda690a127745 (diff)
downloadhtmx-bc95b40004e249075314a119a0f3a1c3bdaed619.tar.gz
htmx-bc95b40004e249075314a119a0f3a1c3bdaed619.zip
Merge remote-tracking branch 'origin/master'
-rw-r--r--www/content/QUIRKS.md2
-rw-r--r--www/content/docs.md3
-rw-r--r--www/content/events.md12
-rw-r--r--www/content/examples/_index.md1
-rw-r--r--www/content/examples/bulk-update.md14
-rw-r--r--www/content/examples/reset-user-input.md80
-rw-r--r--www/templates/404.html11
-rw-r--r--www/themes/htmx-theme/templates/base.html2
8 files changed, 115 insertions, 10 deletions
diff --git a/www/content/QUIRKS.md b/www/content/QUIRKS.md
index b485a766..33c00281 100644
--- a/www/content/QUIRKS.md
+++ b/www/content/QUIRKS.md
@@ -115,7 +115,7 @@ If you want to specifically allow `422` responses to swap, you can use this conf
Here is a meta tag allowing all responses to swap:
```html
- <meta name="htmx-config" content='{"responseHandling": [{"code":"...", "swap": true}]'>
+ <meta name="htmx-config" content='{"responseHandling": [{"code":"...", "swap": true}]}'>
```
## `GET` Requests on Non-Form Elements Do Not Include Form Values by Default
diff --git a/www/content/docs.md b/www/content/docs.md
index 65dbffcd..d891e82b 100644
--- a/www/content/docs.md
+++ b/www/content/docs.md
@@ -1415,6 +1415,9 @@ be possible using a standard `on*` property, but it can be done using the `hx-on
Here the `example` parameter is added to the `POST` request before it is issued, with the value 'Hello Scripting!'.
+Another usecase is to [reset user input](@/examples/reset-user-input.md) on successful requests using the `afterRequest`
+event, avoiding the need for something like an out of band swap.
+
The `hx-on*` attributes are a very simple mechanism for generalized embedded scripting. It is _not_ a replacement for more
fully developed front-end scripting solutions such as AlpineJS or hyperscript. It can, however, augment a VanillaJS-based
approach to scripting in your htmx-powered application.
diff --git a/www/content/events.md b/www/content/events.md
index 568ec94e..39a054b6 100644
--- a/www/content/events.md
+++ b/www/content/events.md
@@ -126,10 +126,12 @@ This event is triggered right before a request is sent. You may not cancel the
### Event - `htmx:beforeSwap` {#htmx:beforeSwap}
-This event is triggered before any new content has been [swapped into the DOM](@/docs.md#swapping). If you call `preventDefault()` on the event to cancel it, no swap will occur.
+This event is triggered before any new content has been [swapped into the DOM](@/docs.md#swapping).
+Most values on `detail` can be set to override subsequent behavior, other than where response headers take precedence.
+If you call `preventDefault()` on the event to cancel it, no swap will occur.
-You can modify the default swap behavior by modifying the `shouldSwap` and `target` properties of the event detail. See
-the documentation on [configuring swapping](@/docs.md#modifying_swapping_behavior_with_events) for more details.
+You can modify the default swap behavior by modifying the `shouldSwap`, `selectOverride`, `swapOverride` and `target` properties of the event detail.
+See the documentation on [configuring swapping](@/docs.md#modifying_swapping_behavior_with_events) for more details.
##### Details
@@ -139,6 +141,10 @@ the documentation on [configuring swapping](@/docs.md#modifying_swapping_behavio
* `detail.requestConfig.elt` - the element that dispatched the request
* `detail.shouldSwap` - if the content will be swapped (defaults to `false` for non-200 response codes)
* `detail.ignoreTitle` - if `true` any title tag in the response will be ignored
+* `detail.isError` - whether error events should be triggered and also determines the values of `detail.successful` and `detail.failed` in later events
+* `detail.serverResponse` - the server response as text to be used for the swap
+* `detail.selectOverride` - add this to use instead of an [`hx-select`](@/attributes/hx-select.md) value
+* `detail.swapOverride` - add this to use instead of an [`hx-swap`](@/attributes/hx-swap.md) value
* `detail.target` - the target of the swap
### Event - `htmx:beforeTransition` {#htmx:beforeTransition}
diff --git a/www/content/examples/_index.md b/www/content/examples/_index.md
index 2ab4b4d7..bc98a29b 100644
--- a/www/content/examples/_index.md
+++ b/www/content/examples/_index.md
@@ -30,6 +30,7 @@ You can copy and paste them and then adjust them for your needs.
| [Animations](@/examples/animations.md) | Demonstrates various animation techniques |
| [File Upload](@/examples/file-upload.md) | Demonstrates how to upload a file via ajax with a progress bar |
| [Preserving File Inputs after Form Errors](@/examples/file-upload-input.md) | Demonstrates how to preserve file inputs after form errors |
+| [Reset User Input](@/examples/reset-user-input.md) | Demonstrates how to reset form inputs after submission |
| [Dialogs - Browser](@/examples/dialogs.md) | Demonstrates the prompt and confirm dialogs |
| [Dialogs - UIKit](@/examples/modal-uikit.md) | Demonstrates modal dialogs using UIKit |
| [Dialogs - Bootstrap](@/examples/modal-bootstrap.md) | Demonstrates modal dialogs using Bootstrap |
diff --git a/www/content/examples/bulk-update.md b/www/content/examples/bulk-update.md
index c164f415..5a503e82 100644
--- a/www/content/examples/bulk-update.md
+++ b/www/content/examples/bulk-update.md
@@ -10,7 +10,7 @@ values in the form submission (`POST` request):
```html
<form id="checked-contacts"
hx-post="/users"
- hx-swap="outerHTML settle:3s"
+ hx-swap="innerHTML settle:3s"
hx-target="#toast">
<table>
<thead>
@@ -36,7 +36,11 @@ values in the form submission (`POST` request):
The server will bulk-update the statuses based on the values of the checkboxes.
We respond with a small toast message about the update to inform the user, and
-use ARIA to politely announce the update for accessibility.
+use an `<output>` element to politely announce the update for accessibility. Note
+that the `<output>` element is appropriate for announcing the result of an action
+in a specific form, but if you need to announce general-purpose messages that are
+not connected to a form it would make sense to use an ARIA live region, eg
+`<p id="toast" aria-live="polite"></p>`.
```css
#toast.htmx-settling {
@@ -139,7 +143,7 @@ You can see a working example of this code below.
}
}
- return `<span id="toast" aria-live="polite">Activated ${activated} and deactivated ${deactivated} users</span>`;
+ return `Activated ${activated} and deactivated ${deactivated} users`;
});
// templates
@@ -148,7 +152,7 @@ You can see a working example of this code below.
<form
id="checked-contacts"
hx-post="/users"
- hx-swap="outerHTML settle:3s"
+ hx-swap="innerHTML settle:3s"
hx-target="#toast"
>
<table>
@@ -164,7 +168,7 @@ You can see a working example of this code below.
</tbody>
</table>
<input type="submit" value="Bulk Update" class="btn primary">
- <span id="toast"></span>
+ <output id="toast"></output>
</form>
<br>`;
}
diff --git a/www/content/examples/reset-user-input.md b/www/content/examples/reset-user-input.md
new file mode 100644
index 00000000..50e87f7d
--- /dev/null
+++ b/www/content/examples/reset-user-input.md
@@ -0,0 +1,80 @@
++++
+title = "Reset user input"
+template = "demo.html"
++++
+
+This example shows how to easily reset user inputs using [`hx-on`](@/attributes/hx-on.md),
+allowing users to make multiple requests without having to manually delete their previous inputs.
+
+The inline script will run on the [`afterRequest`](@/events.md#htmx:afterRequest) event and ensures
+that the form will reset to its initial state as long as the response has a 20x status code:
+
+```html
+<form hx-post="/note"
+ hx-target="#notes"
+ hx-swap="afterbegin"
+ hx-on::after-request="if(event.detail.successful) this.reset()">
+ <div class="form-group">
+ <label>Add a note</label>
+ <input type="text" name="note-text" placeholder="blank canvas">
+ </div>
+ <button class="btn">Add</button>
+</form>
+<ul id="notes"><!-- Response will go here --></ul>
+```
+
+The `reset()` method is only available on `form` elements.
+For other elements, the input value can explicitly selected and reset to a default to achieve the same result.
+The following code is functionally equivalent:
+
+```html
+<div>
+ <label>Add a note</label>
+ <input id="note-input" type="text" name="note-text" placeholder="blank canvas">
+</div>
+<button class="btn primary"
+ hx-post="/note"
+ hx-target="#note"
+ hx-swap="afterbegin"
+ hx-include="#note-input"
+ hx-on::after-request="if(event.detail.successful)
+ document.getElementById('note-input').value = ''">
+ Add
+</button>
+<ul id="notes"><!-- Response will go here --></ul>
+```
+
+{{ demoenv() }}
+
+<script>
+
+ //=========================================================================
+ // Fake Server Side Code
+ //=========================================================================
+
+ // routes
+ init("/demo", function(request) {
+ return formTemplate();
+ })
+
+ onPost("/note", function(request, params) {
+ var note = params['note-text'];
+ if (note) {
+ return `<li>${note}</li>`;
+ }
+ })
+
+ // templates
+ function formTemplate() {
+ return `
+<form hx-post="/note" hx-target="#notes" hx-swap="afterbegin" hx-on::after-request="if(event.detail.successful) this.reset()">
+ <div class="form-group">
+ <label>Add a note</label>
+ <input type="text" name="note-text" placeholder="blank canvas">
+ </div>
+ <button class="btn primary">Add</button>
+</form>
+<ul id="notes"> </ul>`;
+ }
+</script>
+
diff --git a/www/templates/404.html b/www/templates/404.html
new file mode 100644
index 00000000..2753b2a1
--- /dev/null
+++ b/www/templates/404.html
@@ -0,0 +1,11 @@
+{% extends "htmx-theme/templates/base.html" %}
+
+{% block title %}
+ {% set html_title = "&lt;/&gt; htmx ~ 404 Not found " %}
+{% endblock title %}
+
+{% block content %}
+ <h1 style="margin-bottom: 500px;">
+ 404 Not Found
+ </h1>
+{% endblock content %}
diff --git a/www/themes/htmx-theme/templates/base.html b/www/themes/htmx-theme/templates/base.html
index 309b1d77..ea6b194d 100644
--- a/www/themes/htmx-theme/templates/base.html
+++ b/www/themes/htmx-theme/templates/base.html
@@ -9,7 +9,7 @@
{# This block should set html_title appropriately -#}
{% block title %} {% endblock title -%}
<title>{{ html_title | default(value=config.title) | safe }}</title>
- <link rel="canonical" href="{{ current_url | safe }}">
+ {% if current_url %} <link rel="canonical" href="{{ current_url | safe }}"> {% endif %}
{#TODO: only generate this for the home page #}
<link rel="alternate" type="application/atom+xml" title="Sitewide Atom feed" href="/atom.xml">
<link rel="stylesheet" href="/css/site.css">