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
Så i det som håller på att bli en serie, i ett arbetsprojekt ville jag lägga till förmågan till en partiell till automatisk uppdatering på en given tidsskala.
Så här gjorde jag med Alpine.js och HTMX.
Så jag ville att detta skulle vara
Med detta i åtanke började jag bygga en liten JS-modul med Alpine.js och HTMX.
Du kan göra automatiska uppdateringar 'på och av' och'minns' funktioner ganska enkelt med HTMX ensam. Till exempel; använda HTMX-utlösare Du kan verkligen göra en hel del saker.
<div id="campaignemail-request-list" hx-get="@Url.Action("List", "CampaignEmailRequest")" hx-trigger="every 30s" hx-swap="innerHTML">
<partial name="_List" model="@Model"/>
</div>
Tack till @KhalidAbuhakmeh För att du påpekade det här.
Denna kod används faktiskt hx-trigger
för att ställa in den automatiska uppdateringen. Använder bara Alpine.js för att konfigurera HTMX- attributen.
Vad detta verkligen lägger till är användarinteraktion klientsidan, vilket är vad Alpine.js är bra på.
Koden för detta är verkligen ganska kompakt, den är uppdelad i två huvuddelar; en JS-modul, händelsehanterare och HTML.
Modulen är en enkel JS modul som använder Alpine.js för att hantera tillståndet för auto-update. Den använder lokal lagring för att komma ihåg läget för automatisk uppdatering mellan förfrågningar.
Det accepterar paramerna :
endpointId
- ID för det element som skall uppdaterasactionUrl
- url att kallas för att uppdatera elementetinitialInterval
- det initiala intervall som ska användas för automatisk uppdatering (standard är 30 sekunder)Vi kan också se det använder ett par nycklar; dessa används för lokal lagring för att komma ihåg tillståndet för auto-update.
Du kan se att jag använder actionurl
som en del av nyckeln för att göra denna endpoint specifik.
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()
MetodDenna metod möjliggör eller inaktiverar automatisk röstning av ett mål HTML-element med hjälp av HTMX.
endpointId
.fullUrl
) genom att kombinera actionUrl
med aktuell sidas frågesträng.localStorage
(bra som det är ihågkommen mellan webbläsarsessioner).this.autoUpdate
är true
(dvs. röstningen är aktiverad):hx-trigger
för att välja ut varje interval
sekunderhx-swap="innerHTML"
för att ersätta elementets innehållhx-get
för att peka på röstadressenhx-headers
för att lägga till en egen "AutoPoll": "auto"
HuvudlocalStorage
htmx.process(el)
för att låta HTMX känna igen de nya attributenhtmx.ajax()
(inte beroende på HTMX händelse ledningar)this.autoUpdate
är false
(dvs. röstningen är inaktiverad):localStorage
htmx.process(el)
igen för att uppdatera HTMX-beteendeVi har också en gren här för att utföra auto-pollen när den först aktiverats.
const wasPreviouslyEnabled = localStorage.getItem(enabledKey) === 'true';
if (!wasPreviouslyEnabled) {
htmx.ajax('GET', fullUrl, {
target: el,
swap: 'innerHTML',
headers: {AutoPoll: 'auto'}
});
}
Detta utför en HTMX- begäran till fullUrl
och uppdaterar målelementet med svaret. Detta är användbart för att visa användaren hur den automatiska uppdateringen kommer att se ut när de aktiverar den.
Du noterar att vi också skickar ett HTMX-huvud med begäran. Detta är viktigt eftersom det gör det möjligt för oss att upptäcka begäran serversidan.
el.setAttribute('hx-headers', JSON.stringify({ AutoPoll: 'auto' }));
headers: {AutoPoll: 'auto'}
I min serversida upptäcker jag sedan att denna rubrik är inställd med hjälp av
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);
}
Du ska få se att jag bara letar efter huvudet med Request.Headers.TryGetValue("AutoPoll", out _)
Och om det är där jag vet att det är en auto-poll begäran.
Jag tar sedan den nuvarande yime (det är för en fransk kund, så jag konverterar till Paris tid) och visa en skål med tiden.
I detta sammanhang är det viktigt att se till att ShowToast
metod är en enkel förlängning metod som sätter en utlösare för att säga HTMX att visa ett rostat meddelande.
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
}
}));
}
Detta upptäcks sedan av min HTMX rostat bröd komponent som visar meddelandet.
document.body.addEventListener("showToast", (event) => {
const { toast, issuccess } = event.detail || {};
const type = issuccess === false ? 'error' : 'success';
showToast(toast || 'Done!', 3000, type);
});
Detta kallar sedan in min Toast komponent I skrev om här .
Det är ganska enkelt att koppla upp den här modulen, i din main.js \ index.js vad som helst bara importera den och koppla upp den till Fönster
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);
});
});
Vi kallar sedan init-metoden i ASP.NET Razor-koden:
För att göra detta så litet och återanvändbart som möjligt är Razor-koden ganska enkel.
Här kan du se att jag anger dataattributen alpin.js för att ställa in automatisk uppdatering.
Du ser att vi ställer in målet att använda för begäran till campaignemail-request-list
Förutsättningar. Detta är det element som kommer att uppdateras med det nya innehållet.
Det är då inkluderat NÅGRA på sidan.
Nu när en kryssruta är markerad kommer den automatiskt att uppdatera listan var 30 sekunder.
<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>
Och det är det, ganska enkelt rätt. Medel HTMX och Alpine.js för att skapa en enkel automatisk uppdateringskomponent som vi enkelt kan använda från ASP.NET Core.