تحديث جزئي ذاتي التحديث مع Alpine.js و HTMX (العربية (Arabic))

تحديث جزئي ذاتي التحديث مع Alpine.js و HTMX

Comments

NOTE: Apart from English (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

أولاً

في ما يصبح سلسلة، في مشروع عمل أردت أن أضيف القدرة على جزئية إلى التحديث التلقائي على مقياس زمني معين.

هذه هي الطريقة التي فعلت ذلك باستخدام الألبين.ج و HTMX.

لذلك اردت ان يكون هذا

  1. وبالتالي ينبغي أن تكون بسيطة وقائمة بذاتها بما يكفي لتحديث أي عنصر تلقائياً.
  2. ينبغي أن تحترم البارامترات الأوريلية القائمة
  3. ينبغي أن يكون جانب خادوم يمكن كشفه (في ASP.net الأساسية في هذه الحالة)
  4. إذا كان تشغيله ينبغي تمكينه من أجل تلك النقطة وهذا ما ينبغي تذكره بين الطلبات.
  5. ينبغي له أن يقوم بالتحديث فور تمكينه (يعرف المستخدم شكله)
  6. يجب أن تكون قادرة على أن تطفئ بواسطة المستخدم
  7. وينبغي أن يكون من السهل إدراجه في صفحة.

ومع وضع هذا في الاعتبار، شرعت في بناء وحدة صغيرة من طراز JS باستخدام Alpine.js و HTMX.

ملاحظة

يمكنك القيام بتحديثات تلقائية للمميزات 'على و خارج' و'تذكر' ببساطة مع HTMX وحده. على سبيل المثال؛ على سبيل المثال؛ HTMKXXXX مُززززززز يمكنك حقا القيام بالكثير من الأشياء.


<div id="campaignemail-request-list" hx-get="@Url.Action("List", "CampaignEmailRequest")" hx-trigger="every 30s" hx-swap="innerHTML">
    <partial name="_List" model="@Model"/>
</div>

هذا الرمز يستخدم في الواقع hx-trigger لضبط الاستكمال التلقائي. فقط باستخدام Alpin.js لضبط خواص HTMX.

ما يضيفه هذا حقاً هو جانب تفاعل المستخدم مع العميل، وهو ما تجيده الألبين.js.

ألف - القانون

رمز هذا هو حقاً مدمجة جداً، انها مقسمة إلى جزأين رئيسيين، وحدة JS، معالجي الأحداث و HTML.

ألف - الوحدة

وهذه النميطة عبارة عن نميطة بسيطة من النميطة المشتركة تستخدم الألبينية (Alpin.js) لإدارة حالة التحديث الذاتي. وهي تستخدم التخزين المحلي لتذكر حالة التحديث التلقائي بين الطلبات.

« إن » ما « هي » أي ما « هي ».

  • endpointId - هوية العنصر المراد تحديثه
  • actionUrl - أورل الذي سيُستدعى لتحديث العنصر
  • initialInterval - الفترة الأولية التي ستستخدم في التحديث الذاتي (الافتراض هو 30 ثانية)

ويمكننا أيضاً أن نراه يستخدم زوجين من المفاتيح، هذه تستخدم للتخزين المحلي لتذكر حالة التحديث الذاتي. يمكنك أن ترى أنني أستخدم actionurl كجزء من المفتاح لجعل نقطة النهاية هذه محددة.

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() الم

وهذا الأسلوب يمكّن أو يعطل تلقائياً من توجيه عنصر HTML المستهدف باستخدام HTMX.

مُجَرْ مُجَرْ مُنْ مُنْ مُنْ مُنْ مَ

  • endpointId.
  • يدعم عنوان الطلب (%fullUrlبالجمع بين ما يلي : actionUrl مع الحالي سطر.
  • التحقق إذا كان الاقتراع ميسراً للقراءة من localStorage (جيد كما يُذكر بين جلسات المتصفح).

متى متى this.autoUpdate هو true (أي، يُمكَّن الاقتراع من القيام بما يلي:

  • سِيّد::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    • hx-trigger إلى أن تُعلَل interval ثانياً
    • hx-swap="innerHTML" بدلاً من الاستعاضة عن محتوى العنصر
    • hx-get إلى المُلْزِل UR UR
    • hx-headers "AutoPoll": "auto"
  • حفظ الحالة المكف إلى localStorage
  • 1 - يُكفّف على ما يلي: htmx.process(el) إلى السماح HTMX HTMX التعرف على الخصائص الجديدة
  • إذا كان سابقاً يعمل، يقوم فوراً بالضغط على طلب HTMX عن طريق htmx.ajax() (لا تعتمد على أس أساطير الحدث HTMX)

متى متى this.autoUpdate هو false (أي أن يكون الاقتراع معوقاً):

  • يُزال مُسندات العليا
  • يُمح الإعداد المُوفر من localStorage
  • 1 - يُكفّف على ما يلي: htmx.process(el) إلى تحديث HTMX سلوك

هذا

لدينا أيضا فرع هنا لأداء عملية التشغيل الذاتي عندما تم تمكينها في البداية.

const wasPreviouslyEnabled = localStorage.getItem(enabledKey) === 'true';
      if (!wasPreviouslyEnabled) {
                    htmx.ajax('GET', fullUrl, {
                        target: el,
                        swap: 'innerHTML',
                        headers: {AutoPoll: 'auto'}
                    });
                }

هذا الدالة a HTMX طلب إلى fullUrl ويستكمل عنصر الهدف مع الرد. هذا مفيد لعرض المستخدم كيف سيبدو التحديث التلقائي عند تمكينه.

أنت سَتُلاحظُ بأنّنا نُرسلُ أيضاً a HTMX ترويسة مع الطلبِ. هذا مهم لأنه يسمح لنا باكتشاف جانب خادم الطلب.

   el.setAttribute('hx-headers', JSON.stringify({ AutoPoll: 'auto' }));
headers: {AutoPoll: 'auto'}

في جانب خادمي I ثم الكشف عن هذا الترويض الذي يجري تشغيله

 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);
        }

سترى أنا فقط أبحث عن الرأس مع Request.Headers.TryGetValue("AutoPoll", out _) وإذا كان هناك أعرف أنه طلب تلقائي

ثم آخذ الييمي الحالي (إنه لعميل فرنسي، لذا أتحول إلى وقت باريس) وأعرض نخباً مع الوقت.

الـ ShowToast هي عبارة عن طريقة بسيطة للإمتداد التي تُحدِد دافعاً لتُخبر HTMX لعرض رسالة تُحمَص.

    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
            }
        }));

    }

ثم يتم اكتشاف هذا من خلال مكون الـ HTMX المحمص الذي يظهر الرسالة.

document.body.addEventListener("showToast", (event) => {
    const { toast, issuccess } = event.detail || {};
    const type = issuccess === false ? 'error' : 'success';
    showToast(toast || 'Done!', 3000, type);
});

هذا يَدّعي ثمّ إلى مكوّنِي الأول كتب عن هنا .

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

من السهل جدًا وضع هذه الوحدة في الأعلى، في دليلك الرئيسي. js الرئيسية / index.js ايًا كان فقط استوردها وعلقها في النافذة

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);
    });
});

ثم نطلق على طريقة الإدخال في شفرة ASP.NET:

مدوّد المزوّس

لجعل هذا صغير و قابل لإعادة الاستخدام قدر الإمكان شفرة الرازر بسيطة جدا.

يمكنك أن ترى هنا أنا تحديد بيانات Alpene.js إلى setet uniti- update.

  • x-data: هنا حيث ننشئ كائن بيانات Alpin.js.
  • x-init: هذا هو المكان الذي نسميه طريقة فيت على متحكم الاستكمال الذاتي.
  • x- على: التغير: هنا نطلق على طريقة تحديث TopgleAuto على متحكم الاستكمال الذاتي.
  • هذا هو رمز العنصر المراد تحديثه.
  • هذا هو الـ URl إلى تحديث element.
  • هذه هي الفترة الزمنية التي ستستخدم للاستكمال الذاتي (الافتراض هو 30 ثانية).

سترون أننا حددنا الهدف لاستخدامه من أجل الطلب إلى campaignemail-request-list (ج) عنصر من العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر أو العنصر. هذا هو العنصر الذي سيتم تحديثه مع المحتوى الجديد. وهذا بعد ذلك يتضمن بعض الأشياء في الصفحة.

الآن متى a كشّير مربّع هو مؤكّد الإيطالية تحديث قائمة.

            <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>

في الإستنتاج

وهذا هو عليه، الحق بسيط جدا. Leeding HTMX و Alpin.js لإنشاء عنصر تحديث تلقائي بسيط يمكننا استخدامه بسهولة من ASP.NET الأساسية.

logo

©2024 Scott Galloway