# एचटीएमएल के साथ एक स्मार्ट खोज ड्रॉपडाउन

# परिचय

एक पिछले पोस्ट में मैंने आपको दिखाया है कि कैसे एक [Alpine.js और HTMX के उपयोग से खोज ड्रॉपडाउन](/blog/textsearchingpt11) तब मैंने दिखाया कि हम कैसे कर सकते हैं Cross-Site Request बनावट सुरक्षा का उपयोग करते हुए `AntiforgeryRequestToken` जावास्क्रिप्ट के साथ ASP.NET कोर में [डोनट होल कैश को लागू करने के लिए HTMX का उपयोग कर रहा है](/blog/simpledonutholecachingwithhtmx)एक outstanding issue was how it loaded pages.

[TOC]

<!--category-- HTMX, Alpine.js -->
<datetime class="hidden">2024-09-16T22:30</datetime>

# समस्या

समस्या यह थी कि मैं अनुरोधित पृष्ठ लोड करने के लिए HTMX AJAX का उपयोग कर रहा था एक बार आप ड्रॉप डाउन पृष्ठ से परिणाम चुन लिया था

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

समस्या यह थी कि जब यह सही पृष्ठ को लोड करेगा और दिखाए गए यूआरएल को नया एक के साथ अद्यतन करेगा, यह पीछे बटन को बिगाड़ देता है

मेरे साथ [पिछला लेख पिछली बटन सेंनिगन्स पर](/blog/htmxtomakeyoursitemorespalike) यह मैं ठीक करने के लिए चाहते थे कुछ था

# समाधान

पहले की तरह समाधान यह सीधे HTMX को संभालने के लिए करना था

## `_typeahead.cshtml`

```html
<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 लिंक

## `typeahead.js`

मेरे बैकएण्ड जावास्क्रिप्ट कोड में इसे सक्षम करने के लिए मैंने मेरी खोज विधि में निम्नलिखित जोड़ा है ( नीचे दिखाया गया `this.$nextTick` एक अल्पाइन है .js संरचना है जो इस पर विलंब करता है जब तक कि अल्पेन ने ऊपर मैं दिखाया टेम्प्लेट को संसाधित करने के लिए पूरा किया है

मैं फिर उपयोग `htmx.process()` खोज तत्व पर जो HTMX विशेषताओं की आशा के अनुसार काम सुनिश्चित करेगा

```javascript

.then(data => {
 this.results = data;
this.highlightedIndex = -1; // Reset index on new search
 this.$nextTick(() => {
    htmx.process(document.getElementById('searchresults'));
 });
})
```

<details>
<summary>typeahead.js search </summary>

```javascript
   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");
                });
        }
```

</details>
बाद में जब एक पृष्ठ चुना जाता है तो मैं पृष्ठ चुनने के लिए कोड को संभालता हूँ

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

यह खोज परिणामों में लिंक पर क्लिक करके चुना जाता है

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

जो फिर पृष्ठ को लोड करेगा और सही रूप से यूआरएल अद्यतन करेगा.

मेरे पास प्रमूल बॉक्स में कोड भी है जो आपको तीर कुंजी का उपयोग करने के लिए अनुमति देता है और प्रविष्ट करें

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

```

आप देखेंगे कि यह सभी आवश्यक कोड है कि आप सिर्फ प्रविष्ट करने के लिए क्लिक करें और चयनित पृष्ठ पर नेविगेट करने की अनुमति देता है

# अंत में

सिर्फ एक त्वरित अद्यतन लेख मौजूदा खोज ड्रॉपडाउन में उपयोगकर्ता अनुभव को बढ़ाने के लिए जब खोज का प्रयोग करता है।