Back to "Auto-Update Μερική Ενημέρωση με Alpine.js και HTMX"

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

Alpine.js ASP.NET Core HTMX Javascript

Auto-Update Μερική Ενημέρωση με Alpine.js και HTMX

Wednesday, 23 April 2025

Εισαγωγή

Έτσι, σε αυτό που γίνεται μια σειρά, σε ένα έργο εργασίας ήθελα να προσθέσω την ικανότητα για ένα μέρος στην αυτόματη ενημέρωση σε ένα δεδομένο χρονοδιάγραμμα.

Εδώ είναι πώς το έκανα χρησιμοποιώντας Alpine.js και HTMX.

Απαιτήσεις

Οπότε ήθελα αυτό να είναι...

  1. μπορεί να χρησιμοποιηθεί εκ νέου· έτσι θα πρέπει να είναι απλό και αυτόνομο αρκετά για την αυτόματη ενημέρωση οποιουδήποτε στοιχείου.
  2. Θα πρέπει να σέβεται τις υπάρχουσες παραμέτρους URL
  3. Θα πρέπει να είναι ανιχνεύσιμη πλευρά Server (σε ASP.NET πυρήνα σε αυτή την περίπτωση)
  4. Αν ενεργοποιηθεί θα πρέπει να ενεργοποιηθεί για το εν λόγω τελικό σημείο μόνο και αυτό θα πρέπει να θυμόμαστε μεταξύ των αιτήσεων.
  5. Θα πρέπει αμέσως να κάνει την ενημέρωση όταν ενεργοποιηθεί (έτσι ο χρήστης ξέρει πώς μοιάζει)
  6. Θα πρέπει να είναι σε θέση να απενεργοποιηθεί από τον χρήστη
  7. Θα πρέπει να είναι απλό να συμπεριληφθεί σε μια σελίδα.

Με αυτό στο μυαλό άρχισα να φτιάχνω μια μικρή μονάδα JS χρησιμοποιώντας Alpine.js και HTMX.

ΣΗΜΕΙΩΣΗ

Μπορείτε να κάνετε auto ενημερώσεις το 'on και off' και 'θυμηθείτε' χαρακτηριστικά αρκετά απλά με HTMX μόνο. Για παράδειγμα, χρήση HTMX Triggers Μπορείς να κάνεις πολλά πράγματα.


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

Χάρη στην... @KalidAbuhakmeh που το σημάδεψες αυτό.

Αυτός ο κώδικας στην πραγματικότητα χρησιμοποιεί hx-trigger να κανονίσουμε την αυτόματη ενημέρωση. Απλά χρησιμοποιώντας Alpine.js για να ρυθμίσετε τα χαρακτηριστικά HTMX.

Αυτό που πραγματικά προσθέτει αυτό είναι η πλευρά του πελάτη αλληλεπίδρασης χρήστη? Αυτό είναι ό, τι Alpine.js είναι μεγάλη σε.

Ο κώδικας

Ο κώδικας για αυτό είναι πραγματικά αρκετά συμπαγής, είναι χωρισμένος σε δύο κύρια μέρη; ένα JS μονάδα, οι χειριστές γεγονότων και το HTML.

Η ενότητα

Η ενότητα είναι μια απλή ενότητα JS που χρησιμοποιεί Alpine.js για να διαχειριστεί την κατάσταση της αυτόματης ενημέρωσης. Χρησιμοποιεί τοπική αποθήκευση για να θυμηθεί την κατάσταση της αυτόματης ενημέρωσης μεταξύ των αιτήσεων.

Δέχεται τις παρελάσεις:

  • endpointId - την ταυτότητα του προς ενημέρωση στοιχείου
  • actionUrl - το url που καλείται να ενημερώσει το στοιχείο
  • 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.
  • Κατασκευάζει το αίτημα URL (fullUrl) συνδυάζοντας το δεδομένο actionUrl με τη σειρά ερωτήσεων της τρέχουσας σελίδας.
  • Έλεγχος σε περίπτωση που οι δημοσκοπήσεις είχαν ήδη ενεργοποιηθεί από την ανάγνωση από localStorage (καλό όπως θυμάται μεταξύ των συνεδριών του προγράμματος περιήγησης).

Πότε this.autoUpdate ί ας true (δηλαδή, είναι δυνατή η δημοσκόπηση):

  • Ορίζει χαρακτηριστικά HTMX στο στοιχείο:
    • hx-trigger σε δημοσκοπήσεις κάθε interval δευτερόλεπτα
    • hx-swap="innerHTML" για την αντικατάσταση του περιεχομένου του στοιχείου·
    • hx-get για να επισημάνει το URL δημοσκοπήσεων
    • hx-headers για να προσθέσετε ένα έθιμο "AutoPoll": "auto" κεφαλίδα
  • Αποθήκευση της ενεργοποιημένης κατάστασης localStorage
  • Κλήσεις htmx.process(el) να αφήσει HTMX αναγνωρίζουν τα νέα χαρακτηριστικά
  • Εάν ήταν προηγουμένως εκτός λειτουργίας, ενεργοποιεί αμέσως αίτηση HTMX μέσω htmx.ajax() (δεν βασίζεται στην καλωδίωση γεγονότων HTMX)

Πότε this.autoUpdate ί ας false (δηλαδή, οι δημοσκοπήσεις είναι απενεργοποιημένες):

  • Απομακρύνει τα παραπάνω χαρακτηριστικά HTMX
  • Καθαρίζει την αποθηκευμένη ρύθμιση από localStorage
  • Κλήσεις htmx.process(el) again to update HTMX behavior

Auto Poll όταν ενεργοποιήθηκε για πρώτη φορά

Έχουμε επίσης ένα υποκατάστημα εδώ για να εκτελέσει το auto-poll όταν ενεργοποιήθηκε για πρώτη φορά.

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

Αυτό εκτελεί μια αίτηση HTMX στην fullUrl και ενημερώνει το στοιχείο-στόχο με την απάντηση. Αυτό είναι χρήσιμο για να δείξετε στο χρήστη πώς θα μοιάζει το auto-update όταν το ενεργοποιήσουν.

Επικεφαλίδες

Θα σημειώσετε ότι στέλνουμε επίσης κεφαλίδα HTMX με το αίτημα. Αυτό είναι σημαντικό καθώς μας επιτρέπει να ανιχνεύσουμε την πλευρά του διακομιστή αίτησης.

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

Στην πλευρά του διακομιστή μου, τότε ανιχνεύω αυτή την κεφαλίδα που χρησιμοποιείται

 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 _) Και αν είναι εκεί, ξέρω ότι είναι ένα αίτημα για auto-poll.

Στη συνέχεια αρπάζω το τρέχον yime (είναι για έναν Γάλλο πελάτη, έτσι μετατρέπομαι στην ώρα του Παρισιού) και δείχνω μια πρόποση με το χρόνο.

Εμφάνιση πρόποσης@ title: window

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

Αυτό στη συνέχεια καλεί στο τοστ συστατικό μου I έγραψε για εδώ .

Το κρατάω ψηλά.

Είναι πολύ απλό να συνδέσετε αυτό το module επάνω, στο main.js \ index.js σας ό, τι ακριβώς το εισάγετε και να το συνδέσετε με το Window

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

Στη συνέχεια ονομάζουμε τη μέθοδο init στον κώδικα ASP.NET Razor:

ASP.NET Razor Code

Για να γίνει αυτό όσο το δυνατόν πιο μικρό και επαναχρησιμοποίητο ο κώδικας Razor είναι αρκετά απλός.

Εδώ μπορείτε να δείτε I specify the Alpine.js data characters to set the auto-update.

  • x-data: Εδώ εγκαταστήσαμε το αντικείμενο δεδομένων Alpine.js.
  • x-init: Εδώ είναι που ονομάζουμε τη μέθοδο init στο αυτόματο-update controller.
  • x-on: αλλαγή: Εδώ ονομάζουμε τη μέθοδο toggleAutoUpdate στο αυτόματο update controller.
  • data-endpoint-id: Αυτή είναι η ταυτότητα του προς ενημέρωση στοιχείου.
  • data-action-url: Αυτό είναι το url που καλείται να ενημερώσει το στοιχείο.
  • data-interval: Αυτό είναι το διάστημα που πρέπει να χρησιμοποιηθεί για την αυτόματη ενημέρωση (η προεπιλογή είναι 30 δευτερόλεπτα).

Θα δείτε εμείς θέσει το στόχο για να χρησιμοποιήσετε για το αίτημα για την campaignemail-request-list στοιχείο. Αυτό είναι το στοιχείο που θα ενημερωθεί με το νέο περιεχόμενο. Αυτό είναι στη συνέχεια περιλαμβάνονται κάπου στη σελίδα.

Τώρα, όταν ενεργοποιηθεί ένα πλαίσιο ελέγχου, θα ενημερώνει αυτόματα τη λίστα κάθε 30 δευτερόλεπτα.

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

Συμπέρασμα

Και αυτό είναι, πολύ απλό. Leveraging HTMX και Alpine.js για να δημιουργήσετε ένα απλό auto-update συστατικό που μπορούμε να χρησιμοποιήσουμε εύκολα από ASP.NET Core.

logo

©2024 Scott Galloway