This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
En vissel Tour över HTMX-extensioner och hur man använder HT MX med ASP.NET Core
Friday, 02 May 2025
Inleiding
HTMX är en kraftfull JavaScript bibliotek som tillåter dig att skapa dynamiska webbapplikationer med minimalt JavaScript.
Men jag säger fortfarande inte att jag har expertkunskaper om det. Jag ville bara dela med mig av några saker som jag lärt mig på vägen.
Kompanionsartikel: Den här artikeln fokuserar på HTMX's händelsesystem , utvecklingar , och avancerad personalisering M SK3 För ASP.NET Korallintegrationsmönster med partiell syn på systemet HTMX med ASP.
Erfarelser
Förberedels för begäran
Inställningsfasen är den där HTMX konfigurerar inställningen innan den skickas till servern.
flowchart LR
A[htmx:configRequest] --> B[htmx:confirm] --> C[htmx:prompt] --> D[htmx:abort]
begäran om livscykel
Den efterfrågans livscykelfasen är där HTMX skickar in begäran till servern och hanterar svaret. De följande händelserna aktiveras under den här fasen:
flowchart LR E[htmx:beforeRequest] --> F[htmx:request] --> G[htmx:afterRequest]
Reaktionshantering
Response handlingsfasen är när HTMX bearbetar svaret från servern och uppdaterar dom.
flowchart LR
H[htmx:beforeOnLoad] --> I[htmx:onLoad]
I --> J[htmx:beforeSwap] --> K[htmx:swap] --> L[htmx:afterSwap]
L --> M[htmx:afterSettle] --> N[htmx:afterOnLoad]
Historiska avdelningar
Historiens hanteringsfas är när HTMX uppdaterar webbläsarens historia och URL. De följande händelserna aktiveras under den här fasen:
flowchart LR A[htmx:historyRestoreRequest] A --> B[htmx:historyPopped] B --> C[htmx:historyRestorePage]
Som ni kan se så erbjuder HTMX ett antal händelser som du kan koppla in för att modifiera begäran eller svaret.,, eller till och med historien.;. HT MX gör ett LITT för att vara ett så kompaktt system.
Omlängningar
En av de kraftfullaste aspekterna av HTMX är förmågan att skapa förlängningar att utöka dess kapaciteter. I mitt fall htmx:configRequest att lägga till ytterligare parametrar till applikationen. Det är användbart när du vill skicka ytterligare data till servern utan att behöva modifiera HTML eller JavaScript-koden
Andra förlängningar kan hänga htmx:beforeRequest att ändra begäran innan den skickas efter de flesta andra förlängningar som hamnar configRequest; som i beforeRequest saker som HX-Vals och HX-Includes är redan kopplade till den vanligaste ( antingen i payloaden \ querystring
Du kan till och med ha htmx:afterSwap att utföra saker efter att innehållet har bytts ut. Kombinerat med klientseitiga templeringsbibliotek som Alpine.js eller Lit du kan skapa kraftfulla dynamiska applikationer med minimal kod.
HTMX erbjuder några inbyggda extensioner som hx-boost och hx-swap-oob som tillåter dig att förbättra HTMXs funktionalitet utan att skriva någon egen kod.. Men det finns tillfällen då du behöver skapa dina egna förlängningar för att möta specifika krav.
Till exempel, kan du kanske vilja lägga till custom-Header till dina begäran , modifiera begäran-payloaden , eller hantera specifika händelser på ett unikt sätt
För att uppnå detta erbjuder HTMX några praktiska integreringspunkter:
{
/**
* init(api)
* Called once when the extension is initialized.
* Use it to set up internal state, store references, or access HTMX utility functions via the api parameter.
*/
init: function(api) {
return null;
},
/**
* getSelectors()
* Returns additional CSS selectors that HTMX should monitor.
* Useful if your extension needs to handle custom elements or dynamic behavior.
*/
getSelectors: function() {
return null;
},
/**
* onEvent(name, evt)
* Called on every HTMX event (e.g., htmx:beforeRequest, htmx:afterSwap).
* Return false to cancel the event or stop propagation.
*/
onEvent: function(name, evt) {
return true;
},
/**
* transformResponse(text, xhr, elt)
* Modify the raw response text before it is parsed and swapped into the DOM.
* Use this to sanitize or preprocess HTML.
*/
transformResponse: function(text, xhr, elt) {
return text;
},
/**
* isInlineSwap(swapStyle)
* Return true if your extension will handle this swap style manually.
* This tells HTMX to skip default behavior.
*/
isInlineSwap: function(swapStyle) {
return false;
},
/**
* handleSwap(swapStyle, target, fragment, settleInfo)
* Perform custom DOM manipulation if you implement a custom swap style.
* Return true to prevent HTMX's default swap.
*/
handleSwap: function(swapStyle, target, fragment, settleInfo) {
return false;
},
/**
* encodeParameters(xhr, parameters, elt)
* Modify or serialize request parameters before sending.
* Return null to use default URL/form encoding.
* Return a string to override with a custom payload (e.g., JSON).
*/
encodeParameters: function(xhr, parameters, elt) {
return null;
}
}
HTMX erbjuder ett antal pre- byggda förlängningar som du kan läsa om här.
Till exempel en praktisk byggt-in uitbreiding json-encode möjliggör att skicka JSON-data i begäranbasen istället för URL-koderade formdata. Det är användbart när du vill skicka komplexa datastrukturer eller rutnät till servernM SK2
Ni kan se att detta kopplas till 3 händelser.
init- för att sätta upp Erweiterungen och lagra en referens till HTMX APIonEvent- för att sättaContent-Typeheader tillapplication/jsonnär begäran konfigurerasencodeParameters- för att överrida den standardbaserade URL-koderade formkodering och serialisera parametrerna som JSONM SK2 Den återvänder också en ström för att förhindra HTMX från att använda den standardgjorda URL -koderad formkodingMSC4
(function() {
let api
htmx.defineExtension('json-enc', {
init: function(apiRef) {
api = apiRef
},
onEvent: function(name, evt) {
if (name === 'htmx:configRequest') {
evt.detail.headers['Content-Type'] = 'application/json'
}
},
encodeParameters: function(xhr, parameters, elt) {
xhr.overrideMimeType('text/json')
const object = {}
parameters.forEach(function(value, key) {
if (Object.hasOwn(object, key)) {
if (!Array.isArray(object[key])) {
object[key] = [object[key]]
}
object[key].push(value)
} else {
object[key] = value
}
})
const vals = api.getExpressionVars(elt)
Object.keys(object).forEach(function(key) {
// FormData encodes values as strings, restore hx-vals/hx-vars with their initial types
object[key] = Object.hasOwn(vals, key) ? vals[key] : object[key]
})
return (JSON.stringify(object))
}
})
})()
Eller till och med den enklare men ännu mer praktiska hx-debug sträckning som lägger till en HX-Debug header till begäran. Det är användbart för avbugs- och loginsändningar, eftersom det tillåter dig att se råda begäran och reaktionsdata i devkonsolet
(function() {
htmx.defineExtension('debug', {
onEvent: function(name, evt) {
if (console.debug) {
console.debug(name, evt)
} else if (console) {
console.log('DEBUG:', name, evt)
} else {
throw new Error('NO CONSOLE SUPPORTED')
}
}
})
})()
Det finns många fler än "'", med en väldigt kraftfull client side templating extension som låter dig använda klient bibliotek för att omvandla JSON data till HTML. Detta är användbart för att skapa dynamiska gränssnitt utan att behöva lita på servern.
Några anpassade förlängningar
Dynamiska Ry IDs
Till exempel i ett nytt projekt använde jag HTMX OOB-svap för att uppdatera ett antal rader i en tabell. För att göra detta ville jag veta vilka rader som nu visas i tabellen, så jag uppdaterade bara raderna som var synliga.
Extensionen
export default {
encodeParameters: function (xhr, parameters, elt) {
const ext = elt.getAttribute('hx-ext') || '';
if (!ext.split(',').map(e => e.trim()).includes('dynamic-rowids')) {
return null; // Use default behavior
}
const id = elt.dataset.id;
const approve = elt.dataset.approve === 'true';
const minimal = elt.dataset.minimal === 'true';
const single = elt.dataset.single === 'true';
const target = elt.dataset.target;
const payload = { id, approve, minimal, single };
if (approve && target) {
const table = document.querySelector(target);
if (table) {
const rowIds = Array.from(table.querySelectorAll('tr[id^="row-"]'))
.map(row => row.id.replace('row-', ''));
payload.rowIds = rowIds;
}
}
// Merge payload into the parameters object
Object.assign(parameters, payload);
return null; // Return null to continue with default URL-encoded form encoding
}
}
Att använda den
För att använda den behöver vi lägga till den till vår HTMX konfiguration. Så i din ingångspunkt js-lêer ( antagligen att du ' använder moduler; det borde vara
import dynamicRowIds from "./dynamicRowIds"; // Load the file
htmx.defineExtension("dynamic-rowids", dynamicRowIds); // Register the extension
På vilket element du än vill använda den kan du lägga till hx-ext attribut med värdet dynamic-rowids.
<button
hx-ext="dynamic-rowids"
data-target="#my-table"
data-id="@Model.Id"
data-param1="true"
data-param2="false"
data-param3="@Model.Whatever"
hx-post
hx-controller="Contoller"
hx-action="Action"
>
<i class='bx bx-check text-xl text-white'></i>
</button>
Bevara parametrar
Det här är en annan enkel HTMX-extension htmx:configRequest som vi' modifierar URL: n innan rörelsen skickas. Den här utlängningen är tillförlitlig om du använder querystring-baserat filtering, etc.
Detta är SIMILAR till men inte exakt samma som den existerande HTMX-extensionen push-params
Extensionen
Ni kan se att vi onEvent att lyssna på htmx:configRequest händelse.
Så vi:
- få elementet som utlöste händelsen
- Ta den
preserve-params-excludeattribut från elementet ( om det existerar) och delar det i en rad punkter för att utesluta ( så vi inte adderar dem till begäran - få den nuvarande URL-parameterna från vensterlokalen
- få de nya parametrerna från formuläret
- Loopa genom den nuvarande parametern och kolla om de inte är i den uteslutande listan och inte redan i de nya parametrerna
- Om de inte är, så lägger vi dem till de nya parametrerna
- Slutligen, satte vi de nya parametrerna till rörelsens URL och gav tillbaka true för att fortsätta med rörelsen
export default {
onEvent: function (name, evt) {
if (name !== 'htmx:configRequest') return;
const el = evt.detail.elt;
const excludeStr = el.getAttribute('preserve-params-exclude') || '';
const exclude = excludeStr.split(',').map(s => s.trim());
const currentParams = new URLSearchParams(window.location.search);
const newParams = new URLSearchParams(evt.detail.path.split('?')[1] || '');
currentParams.forEach((value, key) => {
if (!exclude.includes(key) && !newParams.has(key)) {
newParams.set(key, value);
}
});
evt.detail.path = evt.detail.path.split('?')[0] + '?' + newParams.toString();
return true;
}
};
Här använder jag HTMX.Net för dess tag hjälpprogram. De liknande hx-controller och hx-action är tagbekymmer som genererar rätta HTMX-Attribute för dig. såväl som hx-route-<x> för värden att passera i vägen. Det är väldigt användbart eftersom det låter dig använda C# kod för att generera korrekta värden för attributen istället för att behöva hårdkoda dem i HTML
Att använda den
Eftersom det är en förlängning så är det väldigt enkelt att använda
Först måste vi lägga till den till vår HTMX konfiguration.
import preserveParams from './preserveParams.js';
htmx.defineExtension('preserve-params', preserveParams);
lägg märke till att standard HTMX-extensioner använder metoden 'autoload' för att ladda extensionen
// Autoloading the extension and registering it
(function() {
htmx.defineExtension('debug', {
}
Det är ett bra sätt att göra det om du använder HTMX i en icke-modulmiljö. import uttalande för att ladda utlängningen och sedan uttryckligen registrera den mot din htmx instance. Det här tillåter dig att dra nytta av trädet -shaking och bara ladda de utlängningar du behöver
Sedan kan du lägga till elementet hx-ext attribut med värdet preserve-params och preserve-params-exclude attribut med en komma-separerad lista av parametrer som ska uteslutas från begäran.
<a class="btn-outline-icon"
hx-controller="MyController"
hx-action="MyAction"
hx-route-myparam="@MyParam"
hx-push-url="true"
hx-ext="preserve-params"
preserve-params-exclude="page,sort"
hx-target="#page-content"
hx-swap="innerHTML show:top"
hx-indicator>
<i class="bx bx-search"></i>
</a>
I det här fallet event.detail.path att ha den nya myparam värde sätter den i den ' kommer ersätta den där med vår nya värde men bevara alla andra ( förutom page och sort). Så vi kan fortsätta skicka alla filter som vi har satt in i URL till servern utan att behöva oroa oss för att de förloras när vi gör en ny begäran
ASP.NET Core
En av de häftiga sakerna med HTMX är att stor del av dess interaktion med servern sker genom HTTP-header. Dessa header ger servern en rik kontext om vad som upplöste begäran , och låter dig svara på det lämpligt från din ASP
Återigen en nyckelkomponent av detta är HTMX.Net. Bland många av sakerna som den erbjuder är prydliga Request utlängningar för att upptäcka HTMX- begäran. Det är användbart för att avgöra om en begäran gjordes av HT MX eller inte , och för att hantera den på det sättet
Det har också sin egen mekanisme för att skicka utlösande signaler
Response.Htmx(h => {
h.WithTrigger("yes")
.WithTrigger("cool", timing: HtmxTriggerTiming.AfterSettle)
.WithTrigger("neat", new { valueForFrontEnd= 42, status= "Done!" }, timing: HtmxTriggerTiming.AfterSwap);
});
Push Urls etc...etc... Khalid gjorde ett fantastiskt jobb med att skapa en uppsättning Erweiterunger för att göra det enkelt att jobba med HTMX i ASP
Det är ett nyckelverktyg i min verktygslåda när jag arbetar med HTMX och ASP Kolla ut det!
Den vanliga HTMX-ansökande opskrifte
Här är en ventilation av de viktigaste opskriften som HTMX skickar med varje begäran.
| Header | Description |
|---|---|
| HX | |
| HX | |
| HX | |
| HX | |
| HX | |
| HX | |
| HX |
Tillåta Erweiterunger
Jag använder dessa ganska mycket i mina ASP-apps Request.IsHtmx() , Request.IsHtmxBoosted() och Request.IsHtmxNonBoosted() du kan enkelt upptäcka HTMX-behov och svara accordingly.
Till exempel, Jag har en väldigt enkel Erweiterung till Beställning som låter mig upptäcka om en begäran är riktad mot mitt huvud #page-content div. Om det är så vet jag att jag borde skicka tillbaka en del
NOTA: Många inser inte att man kan definiera en 'full sida ' som en del
if (Request.PageContentTarget())
{
Response.PushUrl(Request);
return PartialView("List", vm);
}
return View("List", vm);
public static class RequestExtensions
{
public static bool PageContentTarget(this HttpRequest request)
{
bool isPageContentTarget = request.Headers.TryGetValue("hx-target", out var pageContentHeader)
&& pageContentHeader == "page-content";
return isPageContentTarget;
}
}
Reaktionslängder
Förutom förlängningar till begäran, kan du också skapa förlängelser till respons för att skicka händelser tillbaka till klienten.
Ett exempel på SweetAlert
Till exempel i min SweetAlert2 integration Jag gör det möjligt att stänga dialogen med hjälp av en aktivator som ställs från servern.
document.body.addEventListener('sweetalert:close', closeSweetAlertLoader);
Detta aktiveras från servern som en HTMX-utlösande händelse.
public static void CloseSweetAlert(this HttpResponse response)
{
response.Headers.Append("HX-Trigger" , JsonSerializer.Serialize(new
{
sweetalert = "close"
}));
}
Det här kommer att aktivera sweetalert:close händelse på klientsidan, som tillåter dig att stänga dialogen. Du kan också skicka tillbaka data till klienten med hjälp av HX-Trigger header. Det här är användbart för att skicka data från servern till klienten utan att behöva modifiera HTML eller JavaScript kod
Som ni ser, är det väldigt lätt att lyssna på dessa händelser genom att bara lägga till en händelse lyssnare i kroppen.
ShowToast
Jag skrev tidigare om min toastmetod här, men det är det som är värt att nämna här också . För att mycket enkelt kunna få servern att signalera en toast notification på klientens sida, ställde jag ut aktiveringen i den här reaktionsextensionen
public static void ShowToast(this HttpResponse response, string message, bool success = true)
{
response.Headers.Append("HX-Trigger", JsonSerializer.Serialize(new
{
showToast = new
{
toast = message,
issuccess =success
}
}));
}
Sedan kopplar jag in mig i eventclientsidan och ringer till min showToast funktion.
import { showToast, showHTMXToast } from './toast';
window.showHTMXToast = showHTMXToast;
document.body.addEventListener("showToast", showHTMXToast);
Det här låter mig showToast funktion och vält , visar en toast; se mer om det igen i artikeln .
export function showHTMXToast(event) {
const xhr = event?.detail?.xhr;
let type = 'success';
let message = xhr?.responseText || 'Done!';
try {
const data = xhr ? JSON.parse(xhr.responseText) : event.detail;
if (data.toast) message = data.toast;
if ('issuccess' in data) {
type = data.issuccess === false ? 'error' : 'success';
} else if (xhr?.status >= 400) {
type = 'error';
} else if (xhr?.status >= 300) {
type = 'warning';
}
} catch {
if (xhr?.status >= 400) type = 'error';
else if (xhr?.status >= 300) type = 'warning';
}
showToast(message, 3000, type);
}
I slutsats
Ja, det är det.
Related Articles on This Blog
Kompanionsartikel
Detta artikel är en del av en serie med två delar på HTMX med ASP
- HTMX med ASP.NET Corepartial - fokuserar på ASP. Net Core integrering , partiell syn på , HTMX
- Denna artikel - djupt dyka in i HTMX-eventen , livscykeln , utbyggnadsarkitekturen
Fler HTMX-artiklar
- Att lägga till webbningar med HTMX - Implementering av pagination med HTMX
- ASP.Net Core Caching med HTMX - Cachingsstrategier för HTMX-behov
- Auto-refresh med Alpine och HTMX - kombinerar Alpine.js med HTMX för reaktiva komponenter
- Att göra din sida mer SPA-liknande med HTMX - SPA-liknande navigation utan JavaScript ramverk
- Att använda SweetAlert för HX indikatorer - vackra ladeindikatorer med HTMX
- Att visa bröd och bytes med HTMX - Server
Fortsättning avläsning
Officiell HTMX Dokumentation:
- HTMX Dokumentation - Den officiella HTMX-dokumentationen
- HTMX Eventreferens - Hela listan av HTMX händelser
- HTMX-extensioner - De officiella HTMX-extensionerna
- HTMX exempel - Praktiska exempel på HTMX-mönster
- HTMX Essays - Tankfulla artiklar om HTMX-filosofi
Bibliotek & verktyg:
- HTMX.NET GitHub - Bibliotekets källkod
- HTMX.NET NuGet - HTMX.NET på NuGet
- Khalid Abuhakmehs hemsida - skapar HTMX
- Alpine.js Dokumentation - officiella Alpine-docks
Samhällens resurser:
- HTMX-diskord - Aktivt samhällsstöd
- Hypermediasystembok - Gratis online bok om att bygga hypermediaapplikationer