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
Donc dans ce qui devient une série, dans un projet de travail je voulais ajouter la capacité d'une partie à auto-mise à jour sur une échelle de temps donnée.
Voici comment je l'ai fait en utilisant Alpine.js et HTMX.
Donc je voulais que ce soit
Dans cette optique, j'ai entrepris de construire un petit module JS en utilisant Alpine.js et HTMX.
Vous pouvez faire des mises à jour automatiques des fonctionnalités « on and off » et « remember » assez simplement avec HTMX seul. Par exemple, en utilisant Déclencheurs HTMX Tu peux vraiment faire beaucoup de choses.
<div id="campaignemail-request-list" hx-get="@Url.Action("List", "CampaignEmailRequest")" hx-trigger="every 30s" hx-swap="innerHTML">
<partial name="_List" model="@Model"/>
</div>
Grâce à @KhalidAbuhakmeh pour avoir signalé ça.
Ce code utilise en fait hx-trigger
pour mettre en place la mise à jour automatique. Il suffit d'utiliser Alpine.js pour configurer les attributs HTMX.
Ce que cela ajoute vraiment est le côté client de l'interaction utilisateur, ce qui est ce que Alpine.js est excellent.
Le code pour cela est vraiment assez compact, il est divisé en deux parties principales : un module JS, les gestionnaires d'événements et le HTML.
Le module est un simple module JS qui utilise Alpine.js pour gérer l'état de la mise à jour automatique. Il utilise le stockage local pour se souvenir de l'état de la mise à jour automatique entre les requêtes.
Il accepte les params :
endpointId
- l'identifiant de l'élément à mettre à jouractionUrl
- l'url à appeler pour mettre à jour l'élémentinitialInterval
- l'intervalle initial à utiliser pour la mise à jour automatique (par défaut 30 secondes)Nous pouvons également voir qu'il utilise quelques touches ; celles-ci sont utilisées pour le stockage local pour se souvenir de l'état de la mise à jour automatique.
Vous pouvez voir que j'utilise le actionurl
en tant que partie de la clé pour rendre ce paramètre spécifique.
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()
MéthodeCette méthode permet ou désactive le sondage automatique d'un élément HTML cible à l'aide de HTMX.
endpointId
.fullUrl
) en combinant les données suivantes: actionUrl
avec la chaîne de requête de la page actuelle.localStorage
(bien qu'il soit rappelé entre les sessions du navigateur).this.autoUpdate
est true
(c'est-à-dire que le scrutin est activé) :hx-trigger
de procéder à des sondages interval
secondeshx-swap="innerHTML"
pour remplacer le contenu de l'élémenthx-get
pour pointer vers l'URL du sondagehx-headers
pour ajouter une personnalisation "AutoPoll": "auto"
en-têtelocalStorage
htmx.process(el)
pour permettre à HTMX de reconnaître les nouveaux attributshtmx.ajax()
(ne s'appuyant pas sur le câblage d'événements HTMX)this.autoUpdate
est false
(c'est-à-dire que le scrutin est désactivé) :localStorage
htmx.process(el)
à nouveau pour mettre à jour le comportement HTMXNous avons également une branche ici pour effectuer la pollinisation automatique quand elle est activée pour la première fois.
const wasPreviouslyEnabled = localStorage.getItem(enabledKey) === 'true';
if (!wasPreviouslyEnabled) {
htmx.ajax('GET', fullUrl, {
target: el,
swap: 'innerHTML',
headers: {AutoPoll: 'auto'}
});
}
Ceci effectue une requête HTMX à la fullUrl
et met à jour l'élément cible avec la réponse. Ceci est utile pour montrer à l'utilisateur à quoi ressemblera l'auto-update quand ils l'activeront.
Vous noterez que nous envoyons également un en-tête HTMX avec la requête. Ceci est important car il nous permet de détecter le côté serveur de requête.
el.setAttribute('hx-headers', JSON.stringify({ AutoPoll: 'auto' }));
headers: {AutoPoll: 'auto'}
Dans mon côté serveur, je détecte ensuite cet en-tête en utilisant
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);
}
Tu verras que je cherche juste l'en-tête avec Request.Headers.TryGetValue("AutoPoll", out _)
Et si c'est là, je sais que c'est une demande d'autopoll.
J'attrape ensuite le Yime actuel (c'est pour un client français, donc je me convertis à l'heure de Paris) et je porte un toast avec l'heure.
Les ShowToast
méthode est une méthode d'extension simple qui définit un déclencheur pour dire à HTMX de montrer un message toast.
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
}
}));
}
Ceci est ensuite détecté par mon composant HTMX toast qui affiche le message.
document.body.addEventListener("showToast", (event) => {
const { toast, issuccess } = event.detail || {};
const type = issuccess === false ? 'error' : 'success';
showToast(toast || 'Done!', 3000, type);
});
Ceci appelle alors dans mon composant Toast I écrit à propos d'ici .
Il est assez simple de brancher ce module vers le haut, dans votre main.js \ index.js tout ce qui vient de l'importer et le brancher à la fenêtre
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);
});
});
Nous appelons ensuite la méthode init dans le code ASP.NET Razor:
Pour le rendre aussi petit et réutilisable que possible, le code Razor est assez simple.
Ici vous pouvez voir que je spécifie les attributs de données Alpine.js pour configurer l'auto-update.
Vous verrez que nous définissons la cible à utiliser pour la requête à la campaignemail-request-list
élément. C'est l'élément qui sera mis à jour avec le nouveau contenu.
C'est alors inclus quelque part dans la page.
Maintenant, lorsqu'une case à cocher est cochée, la liste sera automatiquement mise à jour toutes les 30 secondes.
<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>
Et c'est tout, assez simple. En utilisant HTMX et Alpine.js pour créer un simple composant de mise à jour automatique, nous pouvons facilement utiliser ASP.NET Core.