Auto-Update Partial Updater avec Alpine.js et HTMX
Introduction
Ainsi, dans ce qui est devenu une série de , dans un projet de travail, j’ai voulu ajouter la capacité d’un partiel à auto-updater sur une période donnée.
Voici ce que j’ai fait avec Alpine.js et HTMX.
Exigences
J'ai donc voulu que ce soit
- reutilisable; de sorte qu’il devrait être simple et autonome-contenant suffisamment pour auto-updater tout élémentM SK2
- Il devrait respecter les paramètres Url existants
- Il doit être détectable du côté serveur (in ASP.NET Core dans cette instanceM SK2
- S'il est activé, il devrait être activé. pour ce point final seulement et cela doit être rappelé entre les demandes.
- Il devrait procéder immédiatement à la mise à jour lorsqu'il est activé (de sorte que l'utilisateur sache comment il se présente )
- Il devrait pouvoir être désactivé par l'utilisateur
- Il devrait être simple d’inclure dans une page.
À cet égard, j’ai décidé de construire un petit module JS en utilisant Alpine.js et HTMX.
Notes
Vous pouvez effectuer des mises à jour automatiques sans les fonctions 'on et offM SK1 et 'remember' assez simplement avec le seul système HTMX Par exemple; en utilisant HTMX Triggers vous pouvez 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>
Merci à @KhalidAbuhakmeh pour souligner ce point.
Ce code utilise en fait hx-trigger pour configurer les attributs HTMX.
C’est la raison pour laquelle HTMX avec Alpine.js est une combinaison si puissante ; HT MX gère l’interaction du serveur et les demandes AJAX, alors que Alpine≥.js gère le état de côté client et l’ interactionM SK5 Vous pouvez-vous aussi faire cela dans Vanilla JSMSC6 OuiMST7 mais vous terminez par écrire un certain nombre de codes pour faire la même chose que ces deux bibliothèques TINY font déjà MST8
Le code
Le code pour cela est vraiment assez compact.
Le module
Le module est un simple module JS qui utilise Alpine.js pour gérer l'état de l'autoM SK1update. Il utilise le stockage local pour se rappeler l'État de l’auto -update entre les demandesMSC4
Il accepte les paramètres :
endpointId- l'ID de l'élément à mettre à jouractionUrl- la URL à appeler pour mettre à jour l'élémentinitialInterval- l'intervalle initial à utiliser pour la mise à jour automatique -update
Nous pouvons également voir qu’il utilise un couple de clés; qui sont utilisées pour le stockage local afin de se rappeler l’état d’autoM SK1update.
Vous pouvez voir que j’utilise actionurl en tant que partie de la clé pour rendre ce point final 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éthode
Cette méthode permet ou désactive le sondage automatique d'un élément HTML cible en utilisant HTMX.
Le comportement
- Sélectionne un élément par son
endpointId. - Construit l'URL de la demande (
fullUrl) en combinant les donnéesactionUrlavec la page courante's chaîne de demande. - Vérifie si le vote a déjà été activé en lisant de
localStorage(bien qu'il soit rappelé entre les sessions du navigateurM SK1
Quand this.autoUpdate est true (iM SK1e ., le vote est activé):
- Détermine les attributs HTMX sur l'élément:
hx-triggerpour le sondage de chaqueinterval2 secondeshx-swap="innerHTML"pour remplacer le contenu de l'élément’hx-getpour indiquer l'adresse URL du scrutinhx-headerspour ajouter une option personnalisée"AutoPoll": "auto"en-tête
- Réserve l'état activé à
localStorage - Les appels
htmx.process(el)pour permettre à HTMX de reconnaître les nouveaux attributs - Si elle était antérieurement hors de service,, il déclenche immédiatement une demande HTMX via
htmx.ajax()(sans dépendre du câblage d'événement HTMX)
Quand this.autoUpdate est false Le vote est désactivé.
- Supprimer les attributs HTMX susmentionnés
- Supprimer les paramètres conservés de
localStorage - Les appels
htmx.process(el)de nouveau pour mettre à jour le comportement HTMX
Enquête automatique lors de la première utilisation
Nous avons également une succursale ici pour effectuer l'auto-poll lorsqu'il est activé pour la première fois.
const wasPreviouslyEnabled = localStorage.getItem(enabledKey) === 'true';
if (!wasPreviouslyEnabled) {
htmx.ajax('GET', fullUrl, {
target: el,
swap: 'innerHTML',
headers: {AutoPoll: 'auto'}
});
}
Cela effectue une demande HTMX à l'adresse suivante : fullUrl et mettre à jour l’élément cible avec la réponse. Ce dernier est utile pour montrer à l’utilisateur quel sera le mode d’affichage automatique de la mise à jour lorsque celui-ci sera activé.
En-têtes
Vous devrez noter que nous envoyons également un HTMX avec la demande. Ceci est important puisqu'il nous permet de détecter le côté du serveur de la demande.
el.setAttribute('hx-headers', JSON.stringify({ AutoPoll: 'auto' }));
headers: {AutoPoll: 'auto'}
Dans mon côté serveur, je détecte ensuite ce titre qui est établi 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);
}
Vous 'Vous verrez que je cherche simplement le titre avec Request.Headers.TryGetValue("AutoPoll", out _) et si c’est là, je sais qu’il s’agit d’une demande automatisée.
Puis je prends le yime actuel (itM SK1s pour un client français ,, puis je convertis à l’heure de Paris) et je montre un toast avec la heureMSC4
Présenter le toast
L'article 5 de la Loi sur l'immigration et le statut des réfugiés ShowToast method est une simple méthode d'extension qui fixe 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
}
}));
}
Cela est alors détecté par mon composant HTMX toast qui montre le message.
document.body.addEventListener("showToast", (event) => {
const { toast, issuccess } = event.detail || {};
const type = issuccess === false ? 'error' : 'success';
showToast(toast || 'Done!', 3000, type);
});
Il s’agit alors de mon composant Toast I. a écrit ici .
Il y a lieu d'en tenir compte.
Il est assez simple de connecter ce module à , dans votre main.
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 d’init dans le code ASP.NET Razor:
ASP.NET Code de razor
Pour le rendre aussi petit et réutilisable que possible, le code Razor est assez simple.
Vous pouvez ici voir que je spécifie les attributs de données Alpine.js pour mettre en place l'auto-updateM SK2
- x-dataM SK1 C'est là que nous avons mis en place l'objet de données Alpine
- x-init: C'est là que nous appelons la méthode d'entrée sur le contrôleur de mise à jour de l'auto
- x-onM SK1change: C'est là que nous appelons la méthode toggleAutoUpdate sur le contrôleur de mise à jour auto -update
- data-endpointM SK1id: C'est l'ID de l'élément à mettre à jour .
- données-actionM SK1url: C'est l'url qui doit être appelé pour mettre à jour l'élément .
- données-intervalleM SK1 C'est l'intervalle qui doit être utilisé pour la mise à jour automatique-update MSC3default est 30 secondesMST5
Vous verrez que nous avons fixé l’objectif à utiliser pour la demande au campaignemail-request-list element. Il s'agit de l'élément qui sera mis à jour avec le nouveau contenu.
Que's ont ensuite été inclus SOMMAIRE sur la page
Maintenant, lorsqu'une case de contrôle est vérifiée, la liste sera automatiquement mise à jour tous les 30 secondesM SK1
<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 conclusion
Et ce n’est pas le cas.