# HTMX (और एक छोटा-सा अल्पियन .js) के लिए ASP में SPA की तरह अनुभव

# परिचय

इस साइट में मैं प्रयोग करता हूँ [HTMX](https://htmx.org/) व्यापक रूप से, यह जावास्क्रिप्ट का बहुत अधिक लिखने के बिना अपने साइट को अधिक प्रतिक्रियात्मक और सुगम बनाने के लिए एक अति आसान तरीका है

**नोट: मैं'मैं अभी तक इस के साथ पूरी तरह से खुश नहीं हूँ**

<datetime class="hidden">2024-09-15T06:45</datetime>

<!--category-- ASP.NET, HTMX, Alpine.js -->
[TOC]

# HTMX और ASP.NET कोर

ASP के साथ HTMX का उपयोग करना [इस पोस्ट](/blog/htmxwithaspnetcore)यह वास्तव में बहुत आसान है 'HTMXify

## सामान्य लिंक

मैं इस साइट पर अधिक से अधिक लिंक बनाने के लिए HTMX का प्रयोग करने का निर्णय किया है।

मैं इसे सिर्फ इस तरह के लिंक टैग में कुछ गुण जोड़ कर प्राप्त करता हूँ

```razor
    <a asp-action="IndexPartial" asp-controller="Home" hx-swap="show:window:top"  hx-target="#contentcontainer" hx-boost="true" class="mr-auto sm:mr-6">
     <div class="svg-container">
        <img src="/img/logo.svg" asp-append-version="true"  width="180px" height="30px"  alt="logo"  :class="{ 'img-filter-dark': isDarkMode }"/>
     </div>
    </a>
```

यहाँ आप देख सकते हैं मैं जोड़ सकता है `hx-swap` विशेषता, यह HTMX को बताता है कि लक्ष्य तत्व की सामग्री को सर्वर से लौटाए गए सामग्री के साथ बदलें

**नोट करें: hx का उपयोग न करें -pushurl क्योंकि इससे ब्राउज़र बैकबटन पर पृष्ठ दो बार पुनः लोड करेगा**

 `hx-target` विशेषता HTMX को बताती है कि कहाँ से सर्वर से लौटाए गए सामग्री रखनी चाहिए `#contentcontainer` तत्व (जहां सभी पृष्ठ सामग्री लोड की जाती है

मैं भी जोड़ता हूँ `hx-swap="show:window:top` जो विंडो को पृष्ठ के शीर्ष पर स्क्रॉल करता है जब सामग्री बदली जाती है

इस का C# भाग काफी सरल है, यह सिर्फ मेरे सामान्य अनुक्रमणिका विधि को दोहराता है लेकिन इसके बजाय आंशिक दृश्य लोड करता है [HTMX.NET](https://github.com/khalidabuhakmeh/Htmx.Net) पता लगाने के लिए `hx-request` शीर्षिका और आंशिक दृश्य लौटाएँ

```csharp
    [Route("/IndexPartial")]
    [OutputCache(Duration = 3600, VaryByHeaderNames = new[] { "hx-request" })]
    [ResponseCache(Duration = 300, VaryByHeader = "hx-request",
        Location = ResponseCacheLocation.Any)]
    [HttpGet]
    public async Task<IActionResult> IndexPartial()
    {
        ViewBag.Title = "mostlylucid";
        if(!Request.IsHtmx()) return RedirectToAction("Index");
        var authenticateResult = await GetUserInfo();
        var posts = await BlogService.GetPagedPosts(1, 5);
        posts.LinkUrl = Url.Action("Index", "Home");
     
        var indexPageViewModel = new IndexPageViewModel
        {
            Posts = posts, Authenticated = authenticateResult.LoggedIn, Name = authenticateResult.Name,
            AvatarUrl = authenticateResult.AvatarUrl
        };
        return PartialView("_HomePartial", indexPageViewModel);
    }
```

इसका परिणाम यह है कि यह लिंक ( और अन्य उसी तकनीक का उपयोग कर रहे हैं \) </a> लोड करने के साथ-साथ |' </A> AJAX </' </b> अनुरोधों और सामग्री को बिना पूरी पृष्ठ पुनः लोड किए बाहर बदल दिया जाता है।

## ब्लॉग लिंक

तो नीचे की विधि काम करने के लिए बनाया जा सकता है however it's super tricky and a bit awkward
HTMX वास्तव में विशेषता आधारित दृष्टिकोण का उपयोग करते हुए काम करना पसंद करता है `htmx.ajax` की तरह है 'if all else fails' विधि और इसका मतलब यह है कि आपको बॉउसर इतिहास के साथ बिगाड़ करना होगा
दुर्भाग्यवश ब्राउज़र इतिहास का उपयोग कर रहा है `pushState` `replaceState` और `popstate` वास्तव में गर्दन में एक थोड़ा दर्द है ( लेकिन किनारे के लिए बहुत शक्तिशाली हो सकता है

इसके बजाय जो मैं कर रहा हूँ यह सिर्फ जोड़ता है `hx-boost` टैग में जो ब्लॉग सामग्री रखता है

```html
   <div class="prose prose max-w-none border-b py-2 text-black dark:prose-dark sm:py-2" hx-boost="true"  hx-target="#contentcontainer">
        @Html.Raw(Model.HtmlContent)
    </div>
```

यह अच्छी तरह से काम करने के लिए लगता है `hx-boost` माता-पिता विधियों पर रखी जा सकती है और सभी बाल लिंकों को लागू किया जा सकता है

दुर्लभ अवसर में आप DON'T विशेष लिंक के लिए HTMX का उपयोग करना चाहते हैं, आप सिर्फ जोड़ सकते है `hx-boost="false"` [लिंक पर](https://htmx.org/attributes/hx-boost/).

## ब्लॉग लिंक (NOTE: मैंने इस दृष्टिकोण को छोड़ दिया लेकिन इसे संदर्भ के लिए यहाँ रखें

लेकिन इस दृष्टिकोण के साथ एक समस्या थी मेरे ब्लॉग लिंक जैसे यह एक [SPA के समान अनुभव के लिए HTMX](/blog/htmxtomakeyoursitemorespalike) जो नहीं हैं 'सामान्यM SK1 लिंक्स. ये लिंक मार्कडाउन पार्सर द्वारा उत्पन्न किए जाते हैं\;\ जबकि मैं लिंकों में एचटीएमएस विशेषताओं को जोड़ने के लिए MarkDig एक्सटेंशन लिख सकता हूँ

इसके बजाय मैंने एक जावास्क्रिप्ट फ़ंक्शन जोड़ा जो इन सभी प्रकार के लिंक को देखता है `htmx.ajax` स्क्वाप करने के लिए यह अनिवार्य रूप से है कि HTMX वैसे भी क्या करता है बस 'मैनुअल

जैसा कि आप देख सकते हैं यह सिर्फ एक सरल फ़ंक्शन है जो सभी लिंक के लिए देखता है `div.prose` तत्व है कि एक के साथ शुरू `/` और फिर उन पर एक घटना श्रोता जोड़ता है. जब लिंक क्लिक किया जाता है तो घटना रोकी जाती है `htmx.ajax` फ़ंक्शन यूआरएल और अद्यतन करने के लिए लक्ष्य तत्व के साथ बुलाया जाता है

```javascript
(function(window) {
   
    window.blogswitcher =() =>  {
        const blogLinks = document.querySelectorAll('div.prose  a[href^="/"]');

        // Iterate through all the selected blog links
        blogLinks.forEach(link => {
            link.addEventListener('click', function(event) {
               event.preventDefault();
                let link = event.currentTarget;
                let url = link.href;
                htmx.ajax('get', url, {
                    target: '#contentcontainer',  // The container to update
                    swap: 'innerHTML',            // Replace the content inside the target


                }).then(function() {
                    history.pushState(null, '', url);
                  
                        window.scrollTo({
                            top: 0,
                            behavior: 'smooth' // For a smooth scrolling effect
                        });
                    
                });
            });
        });
        
    };
})(window);
```

अतिरिक्त एक बार स्क्वाप किया गया है मैं फिर ब्राउज़र इतिहास में नया यूआरएल दबाएँ और पृष्ठ के शीर्ष पर स्क्रॉल करें

## बैक बटन (यह काम करने के लिए मुश्किल है

इस प्रकार के एप्लिकेशन में पीछे बटन समस्या हो सकता है; MANY 'proper\'\ SPAs या तो पीछे बटन को अक्षम कर दें या इस गलत व्यवहार से सहन करें\.\ परन्तु मैं यह सुनिश्चित करना चाहता था कि पीछे बटन अपेक्षित रूप से काम करता है
नोट: बैक बटन को अपेक्षित रूप से काम करने के लिए हम भी के लिए सुनने की जरूरत है `popState` घटना. यह घटना जब उपयोगकर्ता ब्राउज़र इतिहास में पीछे या आगे नेविगेट करता है तब निष्क्रिय होती है

```javascript
window.addEventListener("popstate",   (event) => {
 // When the user navigates back, reload the content for the current URL
 event.preventDefault();
 let url = window.location.href;
 // Perform the HTMX AJAX request to load the content for the current state
 htmx.ajax('get', url, {
  target: '#contentcontainer',
  swap: 'innerHTML'
 }).then(function () {
  // Scroll to the top of the page
  window.scrollTo({
   top: 0,
   behavior: 'smooth'
  });
 });
});
```

इस कोड में हम डिफ़ॉल्ट ब्राउज़र पॉपस्टेट व्यवहार के साथ रोकते हैं `event.preventDefault()` कॉल. हम फिर वर्तमान यूआरएल से बाहर निकालें `window.location.href` गुण और वर्तमान स्थिति के लिए सामग्री लोड करने के लिए HTMX AJAX अनुरोध निष्पादित करें

जैसा कि पहले कहा गया है आप भी उपयोग नहीं कर सकते `hx-pushurl` क्योंकि इससे ब्राउज़र पृष्ठ को दो बार बैकबटन पर पुनः लोड करेगा

# अधिक सामान्य रूप से HTMX (और अल्पियन .jsM SK2

जैसा कि आप अनुमान कर सकते हैं मैं HTMX के एक हद तक एकfan हूँ
मैं अधिक से अधिक 'fully formed' client side frameworks like React के रूप में पसंद करता हूँ। <s> यह मुझे अभी भी एक पूरा सर्वर देता है।
Alpine.js सरल क्लाइंट पक्ष आदान-प्रदान सक्षम करता है

Alpine का उपयोग करने के लिए यह मतलब है कि वहाँ कोई अतिरिक्त जावास्क्रिप्ट की आवश्यकता नहीं है

```razor
        <div class="mb-8 mt-6 border-neutral-400 dark:border-neutral-600 border rounded-lg" x-data="{ showCategories: false }">
            <h4 
                class="px-5 py-1 bg-neutral-500  bg-opacity-10 rounded-lg  font-body text-primary dark:text-white w-full flex justify-between items-center cursor-pointer"
                x-on:click="showCategories = !showCategories"
            >
                Categories
                <span>
                    <i
                        class="bx text-2xl"
                        :class="showCategories ? 'bx-chevron-up' : 'bx-chevron-down'"
                    ></i>
                </span>
            </h4>
            <div 
                class="flex flex-wrap gap-2 pt-2 pl-5 pr-5 pb-2"
                x-show="showCategories" 
                x-cloak
                x-transition:enter="max-h-0 opacity-0"
                x-transition:enter-end="max-h-screen opacity-100"
                x-transition:leave="max-h-screen opacity-100"
                x-transition:leave-end="max-h-0 opacity-0"
            >
                @foreach (var category in ViewBag.Categories)
                {
                    <partial name="_Category" model="category"/>
                }
           
            </div>
        </div>

```

यहाँ आप देख सकते हैं कि मैं उपयोग करता हूँ `x-data` इस मामले में एक नया Alpine.js डेटा ऑब्जेक्ट बनाने के लिए गुण `showCategories`. यह एक बुलियन है जो जब टगल किया जाता है `h4` तत्व क्लिक किया गया है. `x-on:click` गुण का उपयोग टगल फ़ंक्शन में क्लिक घटना को बाइंड करने के लिए किया जाता है

वर्गों की सूची में मैं फिर का उपयोग करता हूँ `x-show` मूल्य पर आधारित वर्गों की सूची दिखाने या छुपाने के लिए विशेषता `showCategories`. मैं भी उपयोग करता हूँ `x-transition` विशेषता को जोड़ने के लिए एक अच्छा स्लाइड नीचे प्रभाव जब वर्ग दिखाया या छुपाए जाते हैं
 `x-cloak` [गुण](https://alpinejs.dev/directives/cloak) को JavaScript चलाने से पहले दिखाए जाने के लिए उपयोग किया जाता है
मैं एक छोटा सीएसएस वर्ग इस के लिए परिभाषित है:

```css
[x-cloak] { display: none !important; }
```

# अंत में

तो यह है कि HTMX का उपयोग करने के बारे में एक छोटा लेख और अपने साइट को अधिक प्रतिक्रियात्मक और महसूस करने के लिए एल्पीन की एक जगह के रूप में।