Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
1cg committed Jan 8, 2025
2 parents 69edc99 + 9062996 commit bc95b40
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 10 deletions.
2 changes: 1 addition & 1 deletion www/content/QUIRKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions www/content/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
12 changes: 9 additions & 3 deletions www/content/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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}
Expand Down
1 change: 1 addition & 0 deletions www/content/examples/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
14 changes: 9 additions & 5 deletions www/content/examples/bulk-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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>
Expand All @@ -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>`;
}
Expand Down
80 changes: 80 additions & 0 deletions www/content/examples/reset-user-input.md
Original file line number Diff line number Diff line change
@@ -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>

11 changes: 11 additions & 0 deletions www/templates/404.html
Original file line number Diff line number Diff line change
@@ -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 %}
2 changes: 1 addition & 1 deletion www/themes/htmx-theme/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down

0 comments on commit bc95b40

Please sign in to comment.