Skip to content

Commit

Permalink
HtmxHeaderTagHelper initial checkin + added sample
Browse files Browse the repository at this point in the history
  • Loading branch information
bingzer committed Oct 11, 2023
1 parent 3d6be82 commit 75ab106
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
54 changes: 54 additions & 0 deletions src/Htmx.TagHelpers/HtmxHeadersTagHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System;
using System.Text.Json;
using System.Text.Json.Nodes;

namespace Htmx.TagHelpers
{
/// <summary>
/// Targets any element that has hx-get, hx-post, hx-put, hx-patch, and hx-delete.
/// https://htmx.org/attributes/hx-headers/
/// </summary>
[PublicAPI]
[HtmlTargetElement("*", Attributes = "[hx-post]")]
[HtmlTargetElement("*", Attributes = "[hx-put]")]
[HtmlTargetElement("*", Attributes = "[hx-delete]")]
[HtmlTargetElement("*", Attributes = "[hx-patch]")]
public class HxHeaders : TagHelper
{
/// <summary>
/// JSON formatted string, a Dictionary or any object.
/// </summary>
[HtmlAttributeName("hx-headers")]
public object Headers { get; set; } = default!;

/// <summary>
/// Dictionary of hx-headers's html attributes
/// </summary>
[HtmlAttributeName("hx-headers", DictionaryAttributePrefix = "hx-headers-")]
public IDictionary<string, string?> HeaderAttributes { get; set; } = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);

public override void Process(TagHelperContext context, TagHelperOutput output)
{
var jsonObject = Headers switch
{
string headerJson => JsonSerializer.Deserialize<JsonObject>(headerJson),
null => null,
_ => JsonSerializer.Deserialize<JsonObject>(JsonSerializer.Serialize(Headers))
} ?? new JsonObject();

// merge
foreach (var jObject in jsonObject)
{
HeaderAttributes[jObject.Key] = jObject.Value?.ToString();
}

// serialize
var json = JsonSerializer.Serialize(HeaderAttributes);

output.Attributes.Add("hx-headers", json);
}
}
}
58 changes: 58 additions & 0 deletions test/Sample/Pages/Headers.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
@page
@using Microsoft.AspNetCore.Antiforgery;
@inject IAntiforgery antiforgery;
@model HxRequestsModel

<div>
<button type="button"
hx-post
hx-page="./Headers"
hx-headers="@(new { button = 1, key1 = "value1", key2 = "value2" })"
hx-swap="innerHTML"
hx-target="#post-result">
Click me (using hx-headers=new object())
</button>
</div>

<div>
<button type="button"
hx-post
hx-page="./Headers"
hx-headers-Button="2"
hx-headers-Key1="value1"
hx-headers-Key2="value2"
hx-swap="innerHTML"
hx-target="#post-result">
Click me (using hx-headers-key="value")
</button>
</div>

<div>
<button type="button"
hx-post
hx-page="./Headers"
hx-headers="@(new { button = 3, key1 = "value1", key2 = "value2" })"
hx-headers-Key3="value3"
hx-headers-Key4="value4"
hx-swap="innerHTML"
hx-target="#post-result">
Click me (using hx-headers and hx-headers-key="value")
</button>
</div>

<div class="mt-2">
<code>requestConfig.headers</code>
<textarea class="w-100" id="post-result" rows="10"></textarea>
</div>

@section Scripts {
<script type="text/javascript">
window.addEventListener("htmx:afterRequest", evt => {
let headers = evt.detail.requestConfig.headers;
let json = JSON.stringify(headers, null, 2);
document.querySelector('#post-result').innerHTML = json;
});
</script>
}

20 changes: 20 additions & 0 deletions test/Sample/Pages/Headers.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Htmx;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Text.Json;

namespace Sample.Pages
{
[ValidateAntiForgeryToken]
public class HxRequestsModel : PageModel
{
public IActionResult OnPost()
{
// list of headers
var headers = Request.Headers.ToList();
var html = "<pre>" + JsonSerializer.Serialize(headers, new JsonSerializerOptions { WriteIndented = true }) + "</pre>";

return Content(html, "text/html");
}
}
}
3 changes: 3 additions & 0 deletions test/Sample/Pages/Shared/_Layout.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Response">Response.Htmx()</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Headers"><code>hx-headers</code></a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
</li>
Expand Down

0 comments on commit 75ab106

Please sign in to comment.