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.
Saturday, 12 April 2025
//Less than a minute
HTMX是一个伟大的图书馆,可以使您的网络应用程序更具活力和响应性。 我将教你们如何使用HTMX在页面上展示敬酒通知和互换内容。
标准 HTMX 中的“限制”之一(即: 非 OOB 互换通常只有从后端交换的单部分内容。 然而,通过使用 HX-Trigger
头头和一个小刺绣。
注:您可以使用 hx-swap-oob
转换两个不同的 内容内容内容 元素,但这个元素比较复杂, 做一些 JavaScripty 的东西并不容易使用。
我一直在使用这个简单的吐吐司通知系统的变种 暂时的.. 这是一个简单的函数, 需要信息、 持续时间和输入( 成功、 错误、 警告) 并在页面上显示敬酒通知 。
这个“ 最新版本” 围绕图标、 动画等等,
// 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 });
}
};
这使用一个小 HTML 片段, 我定义在 _布局. cshtml 文件( 使用我首选的尾风 CSS & DaisiUI) 。 注意结尾处的“阶级保护区块”。 这是一个小把戏,以确保在最后的 HTML 输出中保存分类 。 这真的是为了我的尾风布局,我只看一眼 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>
这里我定义了“ 树木摇晃” 的文件, 并定义了吐司使用的一些动画类 。
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")],
};
秘密 使这一切的 工作是使用 HTMX 触发信头功能.
"通常"现在你会 在您 html / 剃须刀代码中定义此定义:
<div hx-get="/clicked" hx-trigger="click[ctrlKey]">Control Click Me</div>
或者您可以在请求后的事件中定义它 。 所以,你做一些事情 然后它触发了一个新的事件。
<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>
如果你只想做点什么 那就表明已经做了 但我想换掉一些内容 举杯
Response.Headers.Append("HX-Trigger", JsonSerializer.Serialize(new
{
showToast = new
{
toast = result.Message,
issuccess = result.Success
}
}));
如果我的触发器被点名 showToast
我传递信息 和成功旗。 所以我的联署材料 我为这次活动指定了一个活动听众 然后,这等于是说: showToast
和成功标记中的传递功能。
// 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);
});
我为什么要用这个? 在最近的一个工作项目中,我想对一个在表格上展示的用户采取一些行动。 我想展示一个敬酒会通知 并用新内容交换用户行的内容
正如你可以看到的,我有一个BUNCH按钮,它“做一些事情”给用户。 我想展示一个敬酒会通知 并用新内容交换用户行的内容
所以在我的控制下,我有一个简单的“开关”, 它使用动作名称, 做一些东西, 然后返回新的请求结果 。
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
}
}));
}
}
你可以看到我还附上了 HX-Trigger
响应的页眉。 这是JSON的物体 showToast
键和带有 toast
和 issuccess
键。 缩略 toast
键是要在敬杯通知和 issuccess
键是显示该动作是否成功的布尔。
然后在 _Row
我部分拥有 HX (使用 HTMX. Net) 属性来触发动作 。
<!-- 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>
你可以看到我用的是目标 closest tr
将整个行与新内容互换。 这是更新行内容的简单方式, 不必做整页刷新 。
对于ASP.NET核心和HTMX来说,这是非常简单和伟大的技术。
您可以选择使用 HTMX.Nets
但在这种情况下,我只用HTMX回调的这个
[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);
}
在这种情况下,部分意见 _Row
是一个简单的表格行,带有用户信息和要执行动作的按钮。
我还使用另外几个HTMX功能,使用户体验更好。
我也用一个简单的 loading modal
说明请求正在执行中。 这是向用户展示背景中正在发生某事的简单方式。
<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>
我也使用 hx-confirm
属性可在执行动作前显示确认对话框。 这是确保用户真正想要执行该动作的简单方法。 此用途 甜加速器2color 显示确认对话框。
如果您不这样做, HTMX 仍然有效, 但是它使用标准的浏览器“ confirm” 对话框, 这对用户来说有点困难 。
// 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);
});
});
这是使用 HTMX 在页面上显示吐司通知和交换内容的简单方法 。 这是让您的网络应用程序更具活力和响应性的伟大方法。