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
HTMX on loistava kirjasto, joka tekee web-sovelluksistasi entistä dynaamisempia ja reagoivampia. Tässä viestissä näytän, miten HTMX:llä näytetään paahtoleipämainos ja vaihdetaan sisältöä sivulla.
Yksi HTMX-standardin "rajoituksista" (eli ei OMB-swapeja) on se, että sinulla on yleensä vain yksi sisältö vaihdettuna takapäästä. Tämä voidaan kuitenkin ratkaista käyttämällä HX-Trigger
Headers ja pieni javascript.
HUOMAUTUS: Voit käyttää hx-swap-oob
vaihtaa kaksi eri sisältöä elementtejä, mutta tämä on hieman monimutkaisempaa eikä yhtä helppoa käyttää joidenkin JavaScripty-juttujen tekemiseen.
Olen käyttänyt tätä muunnelmaa tästä yksinkertaisesta paahtoleipä-ilmoitusjärjestelmästä. Nyt jo jonkin aikaa...................................................................................................................................... Se on yksinkertainen toiminto, joka vie viestin, keston ja tyypin (menestys, virhe, varoitus) ja näyttää paahtoleipäilmoituksen sivulla.
Tässä "viimeisimmässä versiossa" on lisää blingiä kuvakkeiden, animaatioiden jne. ympärillä...
// HTMX toast notification
// Simple HTMX toast handler for use with hx-on::after-request
window.showToast = (message, duration = 3000, type = 'info') => {
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toast-message');
const toastText = document.getElementById('toast-text');
const toastIcon = document.getElementById('toast-icon');
// Reset classes
toastMessage.className = 'alert shadow-lg gap-2 transition-all duration-300 ease-in-out cursor-pointer';
toastIcon.className = 'bx text-2xl';
// Add DaisyUI alert type
const alertClass = `alert-${type}`;
toastMessage.classList.add(alertClass);
// Add icon class
const iconMap = {
success: 'bx-check-circle',
error: 'bx-error-circle',
warning: 'bx-error',
info: 'bx-info-circle'
};
const iconClass = iconMap[type] || 'bx-bell';
toastIcon.classList.add(iconClass);
// Set the message
toastText.textContent = message;
// Add slide-in animation
toastMessage.classList.add('animate-slide-in');
toast.classList.remove('hidden');
// Allow click to dismiss
toastMessage.onclick = () => hideToast();
// Auto-dismiss
clearTimeout(window.toastTimeout);
window.toastTimeout = setTimeout(() => hideToast(), duration);
function hideToast() {
toastMessage.classList.remove('animate-slide-in');
toastMessage.classList.add('animate-fade-out');
toastMessage.onclick = null;
toastMessage.addEventListener('animationend', () => {
toast.classList.add('hidden');
toastMessage.classList.remove('animate-fade-out');
}, { once: true });
}
};
Tämä käyttää pientä HTML-kimppua, jonka määrittelen omassani _Layout.cshtml-tiedosto (käyttäen suosikkiani Tailwind CSS & DaisyUI). Huomaa lopussa "luokan säilytyspalikka". Tämä on pieni temppu, jolla varmistetaan, että luokat säilyvät lopullisessa HTML-tuotoksessa. Tämä on todella myötätuuleen, kun katson vain cshtml
.
<div
id="toast"
class="toast toast-bottom fixed z-50 hidden w-full md:w-auto max-w-sm right-4 bottom-4"
>
<div
id="toast-message"
class="alert shadow-lg gap-2 transition-all duration-300 ease-in-out cursor-pointer"
>
<i id="toast-icon" class="bx text-2xl"></i>
<span id="toast-text">Notification message</span>
</div>
</div>
<!-- class-preserving dummy block -->
<div class="hidden">
<div class="alert alert-success alert-error alert-warning alert-info"></div>
<i class="bx bx-check-circle bx-error-circle bx-error bx-info-circle bx-bell"></i>
<div class="animate-slide-in animate-fade-out"></div>
</div>
Määritän tässä, mitä tiedostot "puiden shake" ja mitä animaatioluokkia paahtoleipä käyttää.
const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = {
content: ["./Views/**/*.cshtml", "./Areas/**/*.cshtml"],
safelist: ["dark"],
darkMode: "class",
theme: {
extend: {
keyframes: {
'slide-in': {
'0%': { opacity: 0, transform: 'translateY(20px)' },
'100%': { opacity: 1, transform: 'translateY(0)' },
},
'fade-out': {
'0%': { opacity: 1 },
'100%': { opacity: 0 },
},
},
animation: {
'slide-in': 'slide-in 0.3s ease-out',
'fade-out': 'fade-out 0.5s ease-in forwards',
},
},
plugins: [require("daisyui")],
};
Salaisuus saada tämä kaikki toimimaan on käyttää HTMX-laukaisimen toiminnallisuus.
Nyt "normaalisti" tekisit Määrittele tämä varsinaisessa html / partakoneen koodissa:
<div hx-get="/clicked" hx-trigger="click[ctrlKey]">Control Click Me</div>
Tai voit määritellä sen tilausten jälkeisessä tapahtumassa. Joten jos teet jotain, se laukaisee uuden tapahtuman.
<button
hx-get="/api/do-something"
hx-swap="none"
hx-on::afterRequest="window.showToast('API call complete!', 3000, 'success')"
class="btn btn-primary"
>
Do Something
</button>
Tämä on kätevää, jos haluat vain "tehdä jotain, mikä osoittaa, että se on tehty", mutta minun tapauksessani haluan vaihtaa sisältöä ja nostaa maljan.
Response.Headers.Append("HX-Trigger", JsonSerializer.Serialize(new
{
showToast = new
{
toast = result.Message,
issuccess = result.Success
}
}));
Minun tapauksessani liipaisin on nimetty showToast
ja välitän viestin ja menestyslipun. Joten minun JS Olen määritellyt tapahtuman kuuntelijaksi tämän tapahtuman. "Tämän jälkeen showToast
toimi ja kulkee viestissä ja menestyslipussa.
// Handles HX-Trigger: { "showToast": { "toast": "...", "issuccess": true } }
document.body.addEventListener("showToast", (event) => {
const { toast, issuccess } = event.detail || {};
const type = issuccess === false ? 'error' : 'success';
showToast(toast || 'Done!', 3000, type);
});
Miksi käytän tätä? No, tuoreessa työprojektissa halusin ryhtyä toimenpiteisiin pöydässä näkyvän käyttäjän suhteen. Halusin näyttää paahtoleipäilmoituksen ja vaihtaa käyttäjärivin sisällön uuteen sisältöön.
Kuten näette, minulla on BUNCH nappeja, jotka "tekevät juttuja" käyttäjälle. Halusin näyttää paahtoleipäilmoituksen ja vaihtaa käyttäjärivin sisällön uuteen sisältöön.
Joten minun hallinnassani on yksinkertainen "kytkin", joka ottaa toiminnan nimen, tekee juttuja sitten palauttaa uuden pyynnön tulos.
private async Task ApplyAction(string email, string useraction)
{
if (!string.IsNullOrWhiteSpace(useraction) &&
Enum.TryParse<UserActionType>(useraction, true, out var parsedAction))
{
RequestResult result;
switch (parsedAction)
{
case UserActionType.FlipRoles:
result = await userActionService.FlipRestaurantPermissions(email);
break;
case UserActionType.UnflipRoles:
result = await userActionService.UnFlipRestaurantPermissions(email);
break;
case UserActionType.Enable2FA:
result = await userActionService.ToggleMFA(email, true);
break;
case UserActionType.Disable2FA:
result = await userActionService.ToggleMFA(email, false);
break;~~~~
case UserActionType.RevokeTokens:
result = await userActionService.RevokeTokens(email);
break;
case UserActionType.Lock:
result = await userActionService.Lock(email);
break;
case UserActionType.Unlock:
result = await userActionService.Unlock(email);
break;
case UserActionType.Nuke:
result = await userActionService.Nuke(email);
break;
case UserActionType.Disable:
result = await userActionService.DisableUser(email);
break;
case UserActionType.Enable:
result = await userActionService.EnableUser(email);
break;
case UserActionType.ResetPassword:
result = await userActionService.ChangePassword(email);
break;
case UserActionType.SendResetEmail:
result = await userActionService.SendResetEmail(email);
break;
default:
result = new RequestResult(false, "Unknown action");
break;
}
Response.Headers.Append("HX-Trigger", JsonSerializer.Serialize(new
{
showToast = new
{
toast = result.Message,
issuccess = result.Success
}
}));
}
}
Huomaat, että liitän myös HX-Trigger
Header to the reaction. Tämä on JSON-objekti, jossa on showToast
Avain ja arvo esineen kanssa toast
sekä issuccess
Avaimet. Erytropoietiini toast
Avain on viesti, joka näkyy paahtoleipäilmoituksessa ja issuccess
Avain on boolean, joka kertoo, onnistuiko toiminta vai ei.
Ja sitten... _Row
Partial I have the HX (using HTMX.Net) attribuutit käynnistävät toiminnan.
<!-- Revoke Login Tokens -->
<button class="btn btn-xs btn-error border whitespace-normal text-wrap tooltip tooltip-left" data-tip="Revoke login tokens"
hx-get hx-indicator="#loading-modal" hx-target="closest tr" hx-swap="outerHTML"
hx-action="Row" hx-controller="Users"
hx-route-email="@user.Email" hx-route-useraction="@UserActionType.RevokeTokens"
hx-confirm="Are you sure you want to revoke the login tokens for this user?">
<i class="bx bx-power-off"></i> Revoke
</button>
Huomaat, että käytän kohdetta closest tr
vaihtaa koko rivi uuteen sisältöön. Tämä on yksinkertainen tapa päivittää rivin sisältöä ilman koko sivun päivitystä.
Tämä on todella yksinkertainen ja erinomainen tekniikka ASP.NET Corelle HTMX:llä.
Voit käyttää HTMX.Net-verkkoa valinnaisestis
Pyyntö.Onko Htmx täällä, mutta tässä tapauksessa käytän tätä vain HTMX-puhelusta.
[Route("row")]
public async Task<IActionResult> Row(string email, string? useraction = null)
{
if(!string.IsNullOrEmpty(useraction))
await ApplyAction(email, useraction);
var userRow = await userViewService.GetSingleUserViewModel(email);
return PartialView("_Row", userRow);
}
Tässä tapauksessa osittainen näkemys _Row
On yksinkertainen pöytärivi, jossa on käyttäjätiedot ja painikkeet, joilla toiminnot voidaan suorittaa.
Käytän myös paria HTMX-ominaisuutta parantaakseni käyttökokemusta.
Käytän myös yksinkertaista loading modal
ilmoittaa, että pyyntö on käynnissä. Tämä on yksinkertainen tapa näyttää käyttäjälle, että taustalla tapahtuu jotain.
<div id="loading-modal" class="modal htmx-indicator">
<div
class="modal-box flex flex-col items-center justify-center bg-base-200 border border-base-300 shadow-xl rounded-xl text-base-content dark text-center ">
<div class="flex flex-col items-center space-y-4">
<h2 class="text-lg font-semibold tracking-wide">Loading...</h2>
<span class="loading loading-dots loading-xl text-4xl text-stone-200"></span>
</div>
</div>
</div>
Käytän myös hx-confirm
Attribuutti, joka näyttää varmistusikkunan ennen kuin toiminto suoritetaan. Tämä on yksinkertainen tapa varmistaa, että käyttäjä todella haluaa suorittaa toiminnon. Tämä käyttää SweetAlert2 Näyttääksesi varmistusikkunan.
Jos et tee tätä, HTMX toimii yhä, mutta se käyttää vakiona Browser "vahvista" -valintaikkunaa, joka voi olla käyttäjän kannalta hieman sekava.
// HTMX confirm with SweetAlert2
window.addEventListener('htmx:confirm', (e) => {
const message = e.detail.question;
if (!message) return;
e.preventDefault();
Swal.fire({
title: 'Please confirm',
text: message,
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel',
theme: 'dark',
}).then(({ isConfirmed }) => {
if (isConfirmed) e.detail.issueRequest(true);
});
});
Tämä on yksinkertainen tapa käyttää HTMX:ää paahtoleipäilmoituksen näyttämiseen ja sisällön vaihtamiseen sivulla. Tämä on loistava tapa tehdä web-sovelluksistasi dynaamisempia ja reagoivampia.