Μια πιο έξυπνη έρευνα πτώση με HTMX ( ελληνικά (Greek_)

Μια πιο έξυπνη έρευνα πτώση με 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.

Monday, 16 September 2024

//

5 minute read

Εισαγωγή

Σε μια προηγούμενη θέση σας έδειξα πώς να δημιουργήσετε ένα search dropdown using Alpine.js and HTMX τότε έδειξα πώς θα μπορούσαμε να ενεργοποιήσουμε Cross-Site Αίτηση προστασίας πλαστογραφίας χρησιμοποιώντας το AntiforgeryRequestToken σε ASP.NET Core με JavaScript χρησιμοποιώντας HTMX για την εφαρμογή μιας κρύπτης Donut Hole. Ένα εξέχον ζήτημα ήταν το πώς φόρτωνε σελίδες.

Το Πρόβλημα

Το θέμα ήταν ότι χρησιμοποιούσα HTMX AJAX για να κάνω την ζητούμενη φόρτωση σελίδας μόλις είχατε επιλέξει το αποτέλεσμα από την κάτω σελίδα. Αυτό μόνο η Κίντα δούλεψε.

  selectResult(result) {
            htmx.ajax('get', result.url, {
                target: '#contentcontainer',  // The container to update
                swap: 'innerHTML',            // Replace the content inside the target
            }).then(function() {
                history.pushState(null, '', result.url);
                window.scrollTo({
                    top: 0,
                    behavior: 'smooth'
                });
            });

Το θέμα ήταν ότι ενώ αυτό θα φορτώσει τη σωστή σελίδα και την ενημέρωση της εμφανιζόμενης URL με το νέο, καταστράφηκε το πίσω κουμπί. Καθώς η σελίδα δεν ήταν πραγματικά φορτωμένη στην ιστορία σωστά.

Όπως και με το δικό μου τελευταίο άρθρο στο πίσω κουμπί Shennanigans Αυτό ήταν κάτι που ήθελα να διορθώσω.

Η Λύση

Όπως και στο παρελθόν, η λύση ήταν να το χειριστεί άμεσα το HTMX. Για να το κάνω αυτό ενημέρωσα το πρότυπό μου που χρησιμοποιώ για τα αποτελέσματα αναζήτησης.

_typeahead.cshtml

<div x-data="window.mostlylucid.typeahead()" class="relative" id="searchelement" x-on:click.outside="results = []">
    @Html.AntiForgeryToken()
    <label class="input input-sm bg-neutral-500 bg-opacity-10 input-bordered flex items-center gap-2">
        <input
            type="text"
            x-model="query"
            x-on:input.debounce.200ms="search"
            x-on:keydown.down.prevent="moveDown"
            x-on:keydown.up.prevent="moveUp"
            x-on:keydown.enter.prevent="selectHighlighted"
            placeholder="Search..."
            class="border-0 grow input-sm text-black dark:text-white bg-transparent w-full"/>
        <i class="bx bx-search"></i>
    </label>
    <!-- Dropdown -->
    <ul x-show="results.length > 0"
        id="searchresults"
        class="absolute z-100 my-2 w-full bg-white dark:bg-custom-dark-bg border border-1 text-black dark:text-white border-neutral-600 rounded-lg shadow-lg">
        <template x-for="(result, index) in results" :key="result.slug">
            <li :class="{
                'dark:bg-blue-dark bg-blue-light': index === highlightedIndex,
                'dark:hover:bg-blue-dark hover:bg-blue-light': true
            }"
                class="cursor-pointer text-sm p-2 m-2">
                <!-- These are the key changes.-->
                <a
                    x-on:click="selectResult(index)"
                    @* :href="result.url" *@
                    :hx-get="result.url"
                    hx-target="#contentcontainer"
                    hx-swap="innerHTML"
                    hx-push-url="true"
                    x-text="result.title"
                   >
                </a>
                <-- End of changes -->
            </li>
        </template>
    </ul>

</div>

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

typeahead.js

Για να το ενεργοποιήσω αυτό στο backend μου JavaScript code πρόσθεσα τα ακόλουθα στη μέθοδο αναζήτησης μου (shown below). Η this.$nextTick είναι μια κατασκευή Alpine.js που καθυστερεί αυτό μέχρι Alpine έχει τελειώσει την επεξεργασία του προτύπου που έδειξα παραπάνω.

Στη συνέχεια, χρησιμοποιώ htmx.process() σχετικά με το στοιχείο αναζήτησης που θα εξασφαλίσει ότι τα χαρακτηριστικά HTMX λειτουργούν όπως αναμένεται.


.then(data => {
 this.results = data;
this.highlightedIndex = -1; // Reset index on new search
 this.$nextTick(() => {
    htmx.process(document.getElementById('searchresults'));
 });
})
typeahead.js search
   search() {
            if (this.query.length < 2) {
                this.results = [];
                this.highlightedIndex = -1;
                return;
            }
            let token = document.querySelector('#searchelement input[name="__RequestVerificationToken"]').value;
            console.log(token);
            fetch(`/api/search/${encodeURIComponent(this.query)}`, { // Fixed the backtick and closing bracket
                method: 'GET', // or 'POST' depending on your needs
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-TOKEN': token // Attach the AntiForgery token in the headers
                }
            })
                .then(response => {
                    if(response.ok){
                        return  response.json();
                    }
                    return Promise.reject(response);
                })
                .then(data => {
                    this.results = data;
                    this.highlightedIndex = -1; // Reset index on new search
                    this.$nextTick(() => {
                        htmx.process(document.getElementById('searchresults'));
                    });
                })
                .catch((response) => {
                    console.log(response.status, response.statusText);
                    if(response.status === 400)
                    {
                        console.log('Bad request, reloading page to try to fix it.');
                        window.location.reload();
                    }
                    response.json().then((json) => {
                        console.log(json);
                    })
                    console.log("Error fetching search results");
                });
        }
Αργότερα μόλις επιλεγεί μια σελίδα Χειρίζομαι τον κωδικό για να επιλέξω τη σελίδα, κάντε κλικ στο σύνδεσμο ένα σαφές τα αποτελέσματα (για να κλείσετε το πλαίσιο αναζήτησης).
selectHighlighted() {
            if (this.highlightedIndex >= 0 && this.highlightedIndex < this.results.length) {
                this.selectResult(this.highlightedIndex);
                
            }
        },

        selectResult(selectedIndex) {
       let links = document.querySelectorAll('#searchresults a');
       links[selectedIndex].click();
            this.$nextTick(() => {
                this.results = []; // Clear the results
                this.highlightedIndex = -1; // Reset the highlighted index
                this.query = ''; // Clear the query
            });
        }

Αυτό επιλέγεται μέσω του κλικ του συνδέσμου στα αποτελέσματα αναζήτησης.

 <a
  x-on:click="selectResult(index)"
  :hx-get="result.url"
  hx-target="#contentcontainer"
  hx-swap="innerHTML"
  hx-push-url="true"
  x-text="result.title"
  >
  </a>

Το οποίο στη συνέχεια θα φορτώσει τη σελίδα και θα ενημερώσει σωστά το URL.

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

    <label class="input input-sm bg-neutral-500 bg-opacity-10 input-bordered flex items-center gap-2">
        <input
            type="text"
            x-model="query"
            x-on:input.debounce.200ms="search"
            x-on:keydown.down.prevent="moveDown"
            x-on:keydown.up.prevent="moveUp"
            x-on:keydown.enter.prevent="selectHighlighted"
            placeholder="Search..."
            class="border-0 grow input-sm text-black dark:text-white bg-transparent w-full"/>
        <i class="bx bx-search"></i>
    </label>

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

Συμπέρασμα

Απλά ένα γρήγορο άρθρο ενημέρωσης για την υπάρχουσα πτώση αναζήτησης για να ενισχύσει την εμπειρία του χρήστη κατά τη χρήση της αναζήτησης. Και πάλι αυτό είναι ένα MINIMAL χρήστη που αντιμετωπίζει την αλλαγή, αλλά απλά ενισχύει την εμπειρία του χρήστη; ο οποίος ως web developer είναι η κύρια ανησυχία σας (πέρα από την πληρωμή:)).

logo

©2024 Scott Galloway