Ein intelligenter Such-Dropdown mit HTMX (Deutsch (German))

Ein intelligenter Such-Dropdown mit HTMX

Monday, 16 September 2024

//

5 minute read

Einleitung

In einem früheren Beitrag habe ich Ihnen gezeigt, wie man eine Such-Dropdown mit Alpine-.-Js und HTMX dann habe ich gezeigt, wie wir Cross---Site Request Forgery Schutz mit dem AntiforgeryRequestToken im ASP-.-NET Core mit JavaScript mit HTMX einen Donut Hole Cache implementierenEin herausragendes Problem war, wie es Seiten geladen hat.

Das Problem

Das Problem war, dass ich HTMX AJAX benutzte, um die angeforderte Seite zu laden, sobald Sie das Ergebnis aus der Dropdown-Seite ausgewählt hatten.

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

Das Problem war, dass während dies würde laden Sie die richtige Seite und aktualisieren Sie die angezeigte URL mit dem neuen One-, , es verwüstete den Rückwärtsknopf , wie die Seite WASN-' , WIRKLICH in die Geschichte richtig geladen ,. .

Wie bei meinem letzter Artikel auf der Rückseite Knopf Shennanigans das war etwas, was ich reparieren wollte.

Die Lösung

Wie schon zuvor war es die Lösung, HTMX diese direkt behandeln zu lassen..-Um dies zu tun, aktualisierte ich meine Vorlage, die ich für Suchergebnisse verwende

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

Du wirst sehen, dass ich jetzt generiere ordnungsgemäß HTMX-Links in diesem Codeblock - .- Lassen Sie uns das richtige Verhalten verwenden

typeahead.js

Um dies in meinem Backend-JavaScript-Code zu aktivieren, habe ich meiner Suchmethode folgende hinzugefügt: this.$nextTick ist ein alpines Konstrukt, das dieses verzögert, bis Alpine die Bearbeitung der oben gezeigten Vorlage beendet hat

Dann verwende ich htmx.process() auf dem Suchelement, das sicherstellt, dass die HTMX-Attribute wie erwartet funktionieren


.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");
                });
        }
Später, sobald eine Seite ausgewählt ist, handle ich den Code, um die Seite zu wählen.Klicken Sie auf den Link und löschen Sie die Ergebnisse.
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
            });
        }

Dies wird durch den Onclick des Links in den Suchergebnissen ausgewählt.

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

Das wird dann die Seite laden und die URL korrekt aktualisieren.

Ich habe auch Code in der übergeordneten Box whick ermöglicht es Ihnen, die Pfeiltasten zu verwenden und geben Sie...

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

Sie sehen, dass dies alle notwendigen Code hat, damit Sie einfach Enter drücken und zur ausgewählten Seite navigieren können.

Schlussfolgerung

Just a quick update article to the existing search dropdown to enhance the user experience when using such-.. Auch dies ist ein MINIMAL Benutzer gegenüber Änderung, sondern nur verbessert die Benutzererfahrung ?;? wer als Web-Entwickler sind Sie Ihre primäre Sorge

Finding related posts...
logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.