diff options
author | Carson Gross <carson@bigsky.software> | 2025-01-08 12:33:45 -0700 |
---|---|---|
committer | Carson Gross <carson@bigsky.software> | 2025-01-08 12:33:45 -0700 |
commit | bc95b40004e249075314a119a0f3a1c3bdaed619 (patch) | |
tree | a26f89079bb6f000449af9a9bb8b7a63e11f9e13 | |
parent | 69edc99956f2f3dd6e05fd189fdb93e5b12afcac (diff) | |
parent | 906299602552afddcd16cc384c0dda690a127745 (diff) | |
download | htmx-bc95b40004e249075314a119a0f3a1c3bdaed619.tar.gz htmx-bc95b40004e249075314a119a0f3a1c3bdaed619.zip |
Merge remote-tracking branch 'origin/master'
-rw-r--r-- | www/content/QUIRKS.md | 2 | ||||
-rw-r--r-- | www/content/docs.md | 3 | ||||
-rw-r--r-- | www/content/events.md | 12 | ||||
-rw-r--r-- | www/content/examples/_index.md | 1 | ||||
-rw-r--r-- | www/content/examples/bulk-update.md | 14 | ||||
-rw-r--r-- | www/content/examples/reset-user-input.md | 80 | ||||
-rw-r--r-- | www/templates/404.html | 11 | ||||
-rw-r--r-- | www/themes/htmx-theme/templates/base.html | 2 |
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 = "</> 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"> |