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 هي مكتبة كبيرة لجعل تطبيقات الويب الخاص بك أكثر ديناميكية واستجابة. في هذا الموقع، سأريكم كيف تستخدمون HTMX لعرض رسالة نخبية وتبادل المحتوى على الصفحة.
واحدة من "الحدود" في معيار HTMX هي أن لديك عادة فقط قطعة واحدة من المحتوى مبادلة من الطرف الخلفي. ومع ذلك يمكن التغلب على ذلك باستخدام HX-Trigger
رأساً و القليل من الـ (جافاكر)
لقد كنت استخدم هذا البديل من هذا النظام البسيط لإخطارات النخب لفترة من الوقت/ / / / إنها اقتران بسيط يأخذ رسالة، مدة، ونوع (النجاح، الخطأ، الإنذار) ويُظهر إشعاراً بالنخب على الصفحة.
هذا "النسخة الأخيرة" لديها المزيد من التدليك حول الأيقونات، الرسومات...................................................................................................................................................................................................................................................................................................................................................................................................................
// 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 });
}
};
هذا استخدام a قليلاً HTML snippit أنا تعريف بوصة _التصميم. cshtml ملف (باستخدام أفضل ملفاتي في Tayilwind CSS & DesieUI). ملاحظة "الطبقة المحافظة على كتلة" في النهاية. هذه خدعة صغيرة للتأكد من أن الفصول محفوظة في مخرجات 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")],
};
السر في جعل هذا كل ما يعمل هو استخدام مُحرِس مُسند مُراس مُراس مُراس المُراس.
الآن '.......................................................................................... عرّف هذا في 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);
});
إذاً لماذا أستخدم هذا؟ في مشروع عمل حديث أردت اتخاذ بعض الإجراءات على مستخدم عرض في الجدول. أردت أن أعرض تنبيهاً محمصاً ومبادلة محتوى صف المستخدم مع المحتوى الجديد.
كما ترون لدي مجموعة من الأزرار التي "تعمل أشياء" للمستخدم. أردت أن أعرض تنبيهاً محمصاً ومبادلة محتوى صف المستخدم مع المحتوى الجديد.
اذاً في سيطرتي لدي "مفتاح" بسيط يأخذ اسم الفعل، يقوم بالاشياء ثم يرجع نتيجة الطلب الجديد.
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
رأس إلى الإستجابة. هذا هو كائن JJson مع 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 Corre مع HTMX.
يمكنك اختيارياً استخدام HTMX. Nets
طلب. ASHTMX 'هنا ولكن في هذه الحالة أنا فقط من أي وقت مضى استخدام هذا من أي وقت مضى من أي اتصال 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
هو a بسيط جدول صف مع مستخدم معلومات و إلى تنفيذ.
أنا أيضاً أستخدم زوجين من سمات 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
إلى إظهار a تأكيد حوار قبل إجراء هو. هذه طريقة بسيطة للتأكد من أن المستخدم يريد حقا لأداء العمل. هذه الاستخدامات Ail Altert 2 إلى a تأكيد حوار.
الآن إذا كنت لا تفعل هذا، HTMX لا يزال يعمل لكنه يستخدم حوار المتصفح 'concity' المعياري الذي يمكن أن يكون قليلاً من المعايرة للمستخدم.
// 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 لعرض رسالة نخبية ومحتويات مبادلة على الصفحة. هذه طريقة عظيمة لجعل تطبيقات الإنترنت الخاصة بك أكثر ديناميكية واستجابة.