diff --git a/src/Htmx.TagHelpers/HtmxHeadersTagHelper.cs b/src/Htmx.TagHelpers/HtmxHeadersTagHelper.cs new file mode 100644 index 0000000..81f7528 --- /dev/null +++ b/src/Htmx.TagHelpers/HtmxHeadersTagHelper.cs @@ -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 +{ + /// + /// Targets any element that has hx-get, hx-post, hx-put, hx-patch, and hx-delete. + /// https://htmx.org/attributes/hx-headers/ + /// + [PublicAPI] + [HtmlTargetElement("*", Attributes = "[hx-post]")] + [HtmlTargetElement("*", Attributes = "[hx-put]")] + [HtmlTargetElement("*", Attributes = "[hx-delete]")] + [HtmlTargetElement("*", Attributes = "[hx-patch]")] + public class HxHeaders : TagHelper + { + /// + /// JSON formatted string, a Dictionary or any object. + /// + [HtmlAttributeName("hx-headers")] + public object Headers { get; set; } = default!; + + /// + /// Dictionary of hx-headers's html attributes + /// + [HtmlAttributeName("hx-headers", DictionaryAttributePrefix = "hx-headers-")] + public IDictionary HeaderAttributes { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public override void Process(TagHelperContext context, TagHelperOutput output) + { + var jsonObject = Headers switch + { + string headerJson => JsonSerializer.Deserialize(headerJson), + null => null, + _ => JsonSerializer.Deserialize(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); + } + } +} diff --git a/test/Sample/Pages/Headers.cshtml b/test/Sample/Pages/Headers.cshtml new file mode 100644 index 0000000..6058476 --- /dev/null +++ b/test/Sample/Pages/Headers.cshtml @@ -0,0 +1,58 @@ +@page +@using Microsoft.AspNetCore.Antiforgery; +@inject IAntiforgery antiforgery; +@model HxRequestsModel + +
+ +
+ +
+ +
+ +
+ +
+ +
+ requestConfig.headers + +
+ +@section Scripts { + +} + diff --git a/test/Sample/Pages/Headers.cshtml.cs b/test/Sample/Pages/Headers.cshtml.cs new file mode 100644 index 0000000..a2d3048 --- /dev/null +++ b/test/Sample/Pages/Headers.cshtml.cs @@ -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 = "
" + JsonSerializer.Serialize(headers, new JsonSerializerOptions { WriteIndented = true }) + "
"; + + return Content(html, "text/html"); + } + } +} diff --git a/test/Sample/Pages/Shared/_Layout.cshtml b/test/Sample/Pages/Shared/_Layout.cshtml index f1fa0ef..a0d157e 100644 --- a/test/Sample/Pages/Shared/_Layout.cshtml +++ b/test/Sample/Pages/Shared/_Layout.cshtml @@ -37,6 +37,9 @@ +