NOTE: Apart from
(and even then it's questionable, I'm Scottish). These are machine translated in languages I don't read. If they're terrible please contact me.
You can see how this translation was done in this article.
Wednesday, 23 April 2025
//Less than a minute
Dus in wat een serie wordt, in een werkproject wilde ik de mogelijkheid toevoegen voor een gedeeltelijke auto-update op een bepaalde tijdsperiode.
Zo heb ik het gedaan met Alpine.js en HTMX.
Dus ik wilde dat dit zou zijn
Met dit in het achterhoofd wilde ik een kleine JS module bouwen met behulp van Alpine.js en HTMX.
U kunt de 'aan en uit' en 'herinner' functies automatisch updaten met alleen HTMX. Bijvoorbeeld; met behulp van HTMX-triggers Je kunt echt veel dingen doen.
<div id="campaignemail-request-list" hx-get="@Url.Action("List", "CampaignEmailRequest")" hx-trigger="every 30s" hx-swap="innerHTML">
<partial name="_List" model="@Model"/>
</div>
Dankzij @KhalidAbuhakmeh voor het aanwijzen van dit.
Deze code gebruikt in feite hx-trigger
om de auto-update op te zetten. Gewoon met Alpine.js om de HTMX attributen te configureren.
Wat dit echt toevoegt is de gebruiker interactie client kant; dat is waar Alpine.js is geweldig in.
De code voor dit is echt vrij compact, het is opgedeeld in twee hoofdonderdelen; een JS module, de event handlers en de HTML.
De module is een eenvoudige JS module die Alpine.js gebruikt om de staat van de auto-update te beheren. Het gebruikt lokale opslag om de staat van de auto-update tussen verzoeken te onthouden.
Het accepteert de params :
endpointId
- de id van het bij te werken elementactionUrl
- de url die aangeroepen moet worden om het element bij te werkeninitialInterval
- het initiële interval voor de auto-update (standaard is 30 seconden)We kunnen ook zien dat het een paar sleutels gebruikt; deze worden gebruikt voor lokale opslag om de staat van de auto-update te onthouden.
U kunt zien dat ik gebruik maken van de actionurl
als onderdeel van de sleutel om dit eindpunt specifiek te maken.
export function autoUpdateController(endpointId, actionUrl, initialInterval = 30) {
const keyPrefix = `autoUpdate:${actionUrl}`;
const enabledKey = `${keyPrefix}:enabled`;
return {
autoUpdate: false,
interval: initialInterval,
toggleAutoUpdate() {
const el = document.getElementById(endpointId);
if (!el) return;
const url = new URL(window.location.href);
const query = url.searchParams.toString();
const fullUrl = query ? `${actionUrl}?${query}` : actionUrl;
const wasPreviouslyEnabled = localStorage.getItem(enabledKey) === 'true';
if (this.autoUpdate) {
el.setAttribute('hx-trigger', `every ${this.interval}s`);
el.setAttribute('hx-swap', 'innerHTML');
el.setAttribute('hx-get', fullUrl);
el.setAttribute('hx-headers', JSON.stringify({ AutoPoll: 'auto' }));
localStorage.setItem(enabledKey, 'true');
htmx.process(el); // rebind with updated attributes
if (!wasPreviouslyEnabled) {
htmx.ajax('GET', fullUrl, {
target: el,
swap: 'innerHTML',
headers: {AutoPoll: 'auto'}
});
}
} else {
el.removeAttribute('hx-trigger');
el.removeAttribute('hx-get');
el.removeAttribute('hx-swap');
el.removeAttribute('hx-headers');
localStorage.removeItem(enabledKey);
htmx.process(el);
}
},
init() {
this.autoUpdate = localStorage.getItem(enabledKey) === 'true';
this.toggleAutoUpdate();
}
};
}
toggleAutoUpdate()
MethodeDeze methode maakt automatische polling van een target HTML-element met behulp van HTMX mogelijk of schakelt deze uit.
endpointId
.fullUrl
) door het combineren van de gegeven actionUrl
met de huidige pagina's query string.localStorage
(goed als het wordt onthouden tussen browser sessies).this.autoUpdate
is true
(d.w.z. de peiling is ingeschakeld):hx-trigger
om te peilen elke interval
secondenhx-swap="innerHTML"
ter vervanging van de inhoud van het elementhx-get
om te verwijzen naar de stembus URLhx-headers
om een aangepaste toe te voegen "AutoPoll": "auto"
koplocalStorage
htmx.process(el)
om HTMX de nieuwe attributen te laten herkennenhtmx.ajax()
(niet afhankelijk van HTMX event bedrading)this.autoUpdate
is false
(d.w.z. de peiling is uitgeschakeld):localStorage
htmx.process(el)
opnieuw om HTMX-gedrag bij te werkenWe hebben hier ook een branch om de auto-poll uit te voeren wanneer dit voor het eerst is ingeschakeld.
const wasPreviouslyEnabled = localStorage.getItem(enabledKey) === 'true';
if (!wasPreviouslyEnabled) {
htmx.ajax('GET', fullUrl, {
target: el,
swap: 'innerHTML',
headers: {AutoPoll: 'auto'}
});
}
Dit voert een HTMX verzoek naar de fullUrl
en actualiseert het doelelement met de reactie. Dit is handig voor het tonen van de gebruiker hoe de auto-update eruit zal zien wanneer ze het inschakelen.
U zult merken dat we ook een HTMX header sturen met het verzoek. Dit is belangrijk omdat het ons in staat stelt om de request server kant te detecteren.
el.setAttribute('hx-headers', JSON.stringify({ AutoPoll: 'auto' }));
headers: {AutoPoll: 'auto'}
In mijn serverzijde detecteer ik deze header die wordt ingesteld met behulp van
if (Request.Headers.TryGetValue("AutoPoll", out _))
{
var utcDate = DateTime.UtcNow;
var parisTz = TimeZoneInfo.FindSystemTimeZoneById("Europe/Paris");
var parisTime = TimeZoneInfo.ConvertTimeFromUtc(utcDate, parisTz);
var timeStr = parisTime.ToString("yyyy-MM-dd HH:mm:ss");
Response.ShowToast($"Auto Update Last updated: {timeStr} (paris)",true);
return PartialView("_List", requests);
}
Je zult zien dat ik gewoon naar de kop zoek met Request.Headers.TryGetValue("AutoPoll", out _)
En als het daar is, weet ik dat het een autopoll verzoek is.
Ik pak dan de huidige yime (het is voor een Franse klant, dus ik bekeer me naar Parijs tijd) en toon een toast met de tijd.
De ShowToast
methode is een eenvoudige extensie methode die een trigger zet om HTMX te vertellen een toast bericht te tonen.
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
}
}));
}
Dit wordt dan gedetecteerd door mijn HTMX toast component die het bericht toont.
document.body.addEventListener("showToast", (event) => {
const { toast, issuccess } = event.detail || {};
const type = issuccess === false ? 'error' : 'success';
showToast(toast || 'Done!', 3000, type);
});
Dit roept dan in mijn Toast component I schreef over hier .
Het is vrij eenvoudig om deze module aan te koppelen, in je main.js \ index.js wat het ook maar importeert en koppelt het aan Window
import './auto-actions';
window.autoUpdateController = autoUpdateController; //note this isn't strictly necessary but it makes it easier to use in the HTML
//Where we actually hook it up to Alpine.js
document.addEventListener('alpine:init', () => {
Alpine.data('autoUpdate', function () {
const endpointId = this.$el.dataset.endpointId;
const actionUrl = this.$el.dataset.actionUrl;
const interval = parseInt(this.$el.dataset.interval || '30', 10); // default to 30s
return autoUpdateController(endpointId, actionUrl, interval);
});
});
Vervolgens noemen we de init methode in de ASP.NET Razor code:
Om dit zo klein en herbruikbaar mogelijk te maken is de Razor code vrij eenvoudig.
Hier kunt u zien dat ik de Alpine.js data attributen voor het instellen van de auto-update.
U zult zien dat we het doel voor het verzoek aan de campaignemail-request-list
element. Dit is het element dat zal worden bijgewerkt met de nieuwe inhoud.
Dat is dan ergens in de pagina opgenomen.
Wanneer een selectievakje wordt aangevinkt, wordt de lijst elke 30 seconden automatisch bijgewerkt.
<div class=" px-4 py-2 bg-base-100 border border-base-300 rounded-box"
x-data="autoUpdate()"
x-init="init"
x-on:change="toggleAutoUpdate"
data-endpoint-id="campaignemail-request-list"
data-action-url="@Url.Action("List", "CampaignEmailRequest")"
data-interval="30"
>
<label class="flex items-center gap-2">
<input type="checkbox" x-model="autoUpdate" class="toggle toggle-sm" />
<span class="label-text">
Auto update every <span x-text="$data.interval"></span>s
</span>
</label>
</div>
<!-- Voucher List -->
<div id="campaignemail-request-container">
<div
id="campaignemail-request-list">
<partial name="_List" model="@Model"/>
</div>
</div>
En dat is het, vrij eenvoudig rechts. Leveraging HTMX en Alpine.js om een eenvoudige auto-update component te maken die we gemakkelijk kunnen gebruiken van ASP.NET Core.