Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
Provides HTMX integration for ASP.NET Core applications.

<!-- TOC -->
* [HtmxToolkit](#htmxtoolkit)
* [Getting Started](#getting-started)
* [HttpRequest](#httprequest)
* [HtmxRequestAttribute](#htmxrequestattribute)
Expand All @@ -14,6 +15,7 @@ Provides HTMX integration for ASP.NET Core applications.
* [HtmxUrlTagHelper](#htmxurltaghelper)
* [HtmxHeaderTagHelper](#htmxheadertaghelper)
* [HtmxConfigTagHelper](#htmxconfigtaghelper)
* [Response Handling Configuration](#response-handling-configuration)
* [Antiforgery Token](#antiforgery-token)
* [Supported Versions](#supported-versions)
* [Contributions](#contributions)
Expand Down Expand Up @@ -618,6 +620,61 @@ If desired or for the purpose of semantics, you can use `htmx-config` as the sta
include-antiforgery-token="true" />
```

#### Response Handling Configuration

HTMX 2.x introduces the [`responseHandling`](https://htmx.org/docs/#response-handling) configuration option,
allowing you to define how htmx should handle responses based on HTTP status codes.
The library provides a child tag helper `<response-handling>` that can be placed inside `<htmx-config>`
to declaratively configure response handling rules.

```html
<htmx-config>
<!-- 204 No Content — do not swap, but not an error -->
<response-handling code="204" swap="false" />

<!-- 2xx & 3xx — swap into DOM -->
<response-handling code="[23].." swap="true" />

<!-- 422 Unprocessable Entity — swap (e.g. validation errors) -->
<response-handling code="422" swap="true" />

<!-- 4xx & 5xx — do not swap, treat as error -->
<response-handling code="[45].." swap="false" error="true" />

<!-- Catch-all for any other response code -->
<response-handling code="..." swap="true" />
</htmx-config>
```

The following code will be generated:

```html
<meta name="htmx-config"
content='{"responseHandling":[{"code":"204","swap":false},{"code":"[23]..","swap":true},{"code":"422","swap":true},{"code":"[45]..","swap":false,"error":true},{"code":"...","swap":true}]}' />
```

The `<response-handling>` element supports the following attributes:

| Attribute | Type | Description |
|-----------------|----------|------------------------------------------------------------------|
| `code` | `string` | Regular expression tested against response status codes |
| `swap` | `bool?` | Whether the response should be swapped into the DOM |
| `error` | `bool?` | Whether htmx should treat this response as an error |
| `ignore-title` | `bool?` | Whether to ignore title tags in the response |
| `select` | `string` | CSS selector to select content from the response |
| `target` | `string` | CSS selector specifying an alternative target for the response |
| `swap-override` | `string` | Alternative swap mechanism for the response |

Alternatively, you can set the entire response handling configuration directly as a Razor expression:

```html
<htmx-config response-handling="@new [] {
new ResponseHandlingEntry { Code = "204", Swap = false },
new ResponseHandlingEntry { Code = "[23]..", Swap = true },
new ResponseHandlingEntry { Code = "[45]..", Swap = false, Error = true }
}" />
```

## Antiforgery Token

If you have enabled the generation of the **Antiforgery** token in the configuration
Expand Down
8 changes: 7 additions & 1 deletion src/Ramstack.HtmxToolkit/HtmxScrollBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,11 @@ public enum HtmxScrollBehavior
/// <summary>
/// Specifies smooth scrolling to the top of the page.
/// </summary>
Smooth
Smooth,

/// <summary>
/// Specifies instant scrolling with no animation.
/// Supported only in HTMX 2.x.
/// </summary>
Instant
}
33 changes: 20 additions & 13 deletions src/Ramstack.HtmxToolkit/Internal/EnumHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,17 @@ public static string GetWsBinaryTypeValue(this HtmxBinaryType value) =>
/// </summary>
/// <param name="value">The <see cref="HtmxScrollBehavior"/> value.</param>
/// <returns>
/// The string representation: either "auto" or "smooth".
/// The string representation: "auto", "smooth" or "instant".
/// </returns>
public static string GetScrollBehaviorValue(this HtmxScrollBehavior value) =>
value == HtmxScrollBehavior.Auto ? "auto" : "smooth";
public static string GetScrollBehaviorValue(this HtmxScrollBehavior value)
{
return value switch
{
HtmxScrollBehavior.Auto => "auto",
HtmxScrollBehavior.Smooth => "smooth",
_ => "instant"
};
}

/// <summary>
/// Converts a <see cref="HtmxSwap"/> value to its corresponding string representation,
Expand All @@ -47,17 +54,17 @@ public static string GetScrollBehaviorValue(this HtmxScrollBehavior value) =>
/// </returns>
public static string GetSwapValue(this HtmxSwap value)
{
switch (value)
return value switch
{
case HtmxSwap.InnerHtml: return "innerHTML";
case HtmxSwap.OuterHtml: return "outerHTML";
case HtmxSwap.BeforeBegin: return "beforebegin";
case HtmxSwap.AfterBegin: return "afterbegin";
case HtmxSwap.BeforeEnd: return "beforeend";
case HtmxSwap.AfterEnd: return "afterend";
case HtmxSwap.Delete: return "delete";
default: return "none";
}
HtmxSwap.InnerHtml => "innerHTML",
HtmxSwap.OuterHtml => "outerHTML",
HtmxSwap.BeforeBegin => "beforebegin",
HtmxSwap.AfterBegin => "afterbegin",
HtmxSwap.BeforeEnd => "beforeend",
HtmxSwap.AfterEnd => "afterend",
HtmxSwap.Delete => "delete",
_ => "none"
};
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Ramstack.HtmxToolkit.TagHelpers;
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(HtmxConfigTagHelper.HtmxConfiguration))]
[JsonSerializable(typeof(HtmxConfigTagHelper.AntiForgeryTokenData))]
[JsonSerializable(typeof(HtmxConfigTagHelper.AntiForgeryTokenData?))]
[JsonSerializable(typeof(IList<ResponseHandlingEntry>))]
internal partial class HtmxConfigJsonSerializerContext : JsonSerializerContext;
#endif
Loading
Loading