Alpine.js ja HTMX mahdollistivat ASP.NET Coren tag-auttajan (Suomi (Finnish))

Alpine.js ja HTMX mahdollistivat ASP.NET Coren tag-auttajan

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.

Wednesday, 23 April 2025

//

Less than a minute

Johdanto

Vain pikainen, minulla oli tarve työprojektiin, jolla pystyin "tyhjentämään" URL-parametrit URL-osoitteesta. Tämä on hyödyllistä, kun sinulla on URL, jossa on useita parametreja, ja haluat poistaa yhden tai useamman niistä (esimerkiksi hakusuodattimen).

Ongelma

Nykyinen projektini käyttää vanhan koulukunnan kyselyn naruja (se on admin-sivusto, joten se ei tarvitse "kivoja" urluksia. Joten päädyin tällaiseen URL-osoitteeseen:

/products?category=electronics&search=wireless+headphones&sort=price_desc&inStock=true&page=3

Nyt nämä voivat vaihdella joka sivulla, joten voin päätyä BUNCH sivulle URL ja minun täytyy pystyä poistamaan ne kirjoittamatta nippu kattilalevyä tehdä sitä.

Voit tehdä tämän osana mitä tahansa syötönhallintaa, jota käytät, esimerkiksi jokaisen valintaruudun vieressä (tai hienon paikannustyylin selkeä kuvake), mutta voit käyttää tätä tekniikkaa myös niihin. Tässä tapauksessa halusin kuitenkin tehdä kaksi pääasiaa:

  1. Pystyt tyhjentämään nimetyn parametrin
  2. Pystyt tyhjentämään listan parametreista.
  3. Pystyt tyhjentämään kaikki muuttujat
  4. Pyydä se takaisin HTMX:llä
  5. Anna sen käyttää latausmittariani. Lastausmittarini.

Ratkaisu

Projektissani käytän jo

  • HTMX
  • Alppi.js
  • ASP.NET-ydin
  • Perätuulijärjestelmä
  • DaisyUI

Joten ratkaisuni keskittyi näiden käyttöön, jotta saataisiin mukavan näköinen ja toimiva ratkaisu, jossa koodi olisi minimaalinen.

Tagin auttaja

TagHelper on aika yksinkertainen, minä vain luon <a> Parilla ominaisuudella varustettu tagi siirtyy myöhemmin alppimoduuliin, ja olemme valmiita.

[HtmlTargetElement("clear-param")]
public class ClearParamTagHelper : TagHelper
{
    [HtmlAttributeName("name")]
    public string Name { get; set; }
    
    [HtmlAttributeName("all")]
    public bool All { get; set; }= false;
    
    [HtmlAttributeName("target")]
    public string Target { get; set; } = "#page-content";

    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "a";
        output.Attributes.SetAttribute("x-data", "window.queryParamClearer({})");

        if (All)
        {
        output.Attributes.SetAttribute("x-all", All);
        }
        else
        {
            output.Attributes.SetAttribute("x-param", Name);
        }
        output.Attributes.SetAttribute("data-target", Target);
        output.Attributes.SetAttribute("x-on:click.prevent", "clearParam($event)");
        output.Content.SetHtmlContent(@"
            <div class='w-6 h-6 flex items-center justify-center bg-red-600 text-white rounded-full'>
                <i class='bx bx-x text-lg'></i>
            </div>");
    }
}

Parametrit

Käytössä tämä näyttää tältä, ensin "selvennä kaikki parametrit". Joten katsoin vain... Context.Request.Query Jos siinä on mitään parametreja, teen x kuvake antaa käyttäjän tyhjentää kaikki parametrit.


@if(Context.Request.Query.Any())
{
<label class="param-label">
    <clear-param all="true"></clear-param>
    clear all
</label>
}
</div>

Vaihtoehtoisesti voin tehdä tämän nimettyjen parametrien osalta


<div class="param-label">
    <clear-param name="myParam"></clear-param>
    <p>My Param: @Model.MyParam</p>
</div>

Mikä tietysti poistaisi yhden parametrin.

Tai edes


<div class="param-label">
    <clear-param name="myParam1,myParam2,myParam3"></clear-param>
    <p>My Param: @Model.MyParam1</p>
    <p>My Param: @Model.MyParam2</p>
    <p>My Param: @Model.MyParam3</p>
</div>

Tämä poistaa kaikki nimetyt parametrit merkkijonosta.

Erytropoietiini target Ominaisuus

YOU:lla on myös mahdollisuus läpäistä target Ominaisuus, jota käytetään hx-target Ominaisuus. Tämä on hyödyllistä, jos haluat päivittää sivun tietyn osan uudella sisällöllä.


<div class="param-label">
    <clear-param name="myParam" target="#my-thing"></clear-param>
    <p>My Param: @Model.MyParam</p>
</div>

Omassa tapauksessani (koska kirjoitin sen) laiminlöin kohteen #page-content div.

    [HtmlAttributeName("target")]
    public string Target { get; set; } = "#page-content";

Tulos

Nämä johtavat seuraavan HTML:n renderointiin:

  • Kaikki: Joten saamme HTML kanssa x-all Ominaisuus ja ei x-param Ominaisuus.
<a x-data="window.queryParamClearer({})" x-all="True" data-target="#page-content" x-on:click.prevent="clearParam($event)">
    <div class="w-6 h-6 flex items-center justify-center bg-red-600 text-white rounded-full">
        <i class="bx bx-x text-lg"></i>
    </div>
</a>

  • Yksittäinen Saamme HTML:n x-param Ominaisuus ja ei x-all Ominaisuus.
<a x-data="window.queryParamClearer({})" x-param="myParam" data-target="#page-content" x-on:click.prevent="clearParam($event)">
    <div class="w-6 h-6 flex items-center justify-center bg-red-600 text-white rounded-full">
        <i class="bx bx-x text-lg"></i>
    </div>
</a>
  • Useita Saamme HTML:n x-param Attribuutti pilkulla erotellulla merkkijonolla ja ei x-all Ominaisuus.
<a x-data="window.queryParamClearer({})" x-param="myParam1,myParam2,myParam3" data-target="#page-content" x-on:click.prevent="clearParam($event)">
    <div class="w-6 h-6 flex items-center justify-center bg-red-600 text-white rounded-full">
        <i class="bx bx-x text-lg"></i>
    </div>
</a>

Kullakin heistä on myös Alppien kaksi ominaisuutta x-data sekä x-on:click.prevent joita käytetään alppimoduulin perustamisessa ja joissa toimintoa käytetään parametrien selvittämiseen.

Katsotaan, miten se toimii seuraavaksi.

Alppien moduli

Tämä on tietysti mahdollista Alpine.js:n avulla, jotta voimme määrittää pyyntömme ja HTMX:n suorituksen.

Kuten näet alla olevasta koodista, minulla on yksinkertainen moduuli, joka vie path nykyisen sivun ja sitten käyttää URL API tulkitaksesi kyselyjonon (voit myös läpäistä eri syyn :).

Saamme sitten elementti, joka oli klikattu ja tarkistaa, onko se on x-all attribuutti; jos se poistaa kaikki muuttujat URL-osoitteesta, muuten jaamme x-param Määritä pilkuilla ja poista jokainen näistä muuttujista.

Sitten luomme uuden URL-osoitteen päivitetyllä kyselyjonolla ja esitämme pyynnön HTMX-osoitteelle.

export function queryParamClearer({ path = window.location.pathname }) {
    return {
        clearParam(e) {
            const el = e.target.closest('[x-param],[x-all]');
            if (!el) return;

            const url = new URL(window.location.href);

            if (el.hasAttribute('x-all')) {
                // → delete every single param
                // we copy the keys first because deleting while iterating modifies the collection
                Array.from(url.searchParams.keys())
                    .forEach(key => url.searchParams.delete(key));
            } else {
                // → delete only the named params
                (el.getAttribute('x-param') || '')
                    .split(',')
                    .map(p => p.trim())
                    .filter(Boolean)
                    .forEach(key => url.searchParams.delete(key));
            }

            const qs = url.searchParams.toString();
            const newUrl = path + (qs ? `?${qs}` : '');

            showAlert(newUrl);
            htmx.ajax('GET', newUrl, {
                target: el.dataset.target || el.getAttribute('hx-target') || 'body',
                swap: 'innerHTML',
                pushUrl: true
            });
        }
    };
}

//In your entry point / anywhere you want to register the module
import { queryParamClearer } from './param-clearer.js'; // webpackInclude: true

window.queryParamClearer = queryParamClearer;

Erytropoietiini showAlert Funktio käyttää SweetAlert2

Huomaat myös, että kutsun showAlert Funktio. Tämä on vain yksinkertainen kääre SweetAlert2-latausmittarin ympärille, jota käytän projektissani. Voit tietysti korvata tämän sillä, mitä haluat tehdä."

Tätä on hieman muokattu viimeksi näimme sen...................................................................................................................................... Jotta voisin ottaa sen pois. showAlert Toimi ja anna se ulkopuolisten moduulien käyttöön. Joka antaa minun käyttää sitä molemmissa param-clearer Moduuli ja hx-indicator moduuli.

export function registerSweetAlertHxIndicator() {
    document.body.addEventListener('htmx:configRequest', function (evt) {
        const trigger = evt.detail.elt;

        const indicatorAttrSource = getIndicatorSource(trigger);
        if (!indicatorAttrSource) return;

        // ✅ If this is a pageSize-triggered request, use our custom path
        let path;
        if (evt.detail.headers?.['HX-Trigger-Name'] === 'pageSize') {
            path = getPathWithPageSize(evt.detail);
            console.debug('[SweetAlert] Using custom path with updated pageSize:', path);
        } else {
            path = getRequestPath(evt.detail);
        }

        if (!path) return;
        evt.detail.indicator = null;
        showAlert(path);
    });
}

export function showAlert(path)
{
    const currentPath = sessionStorage.getItem(SWEETALERT_PATH_KEY);

    // Show SweetAlert only if the current request path differs from the previous one
    if (currentPath !== path) {
        closeSweetAlertLoader();
        sessionStorage.setItem(SWEETALERT_PATH_KEY, path);


        Swal.fire({
            title: 'Loading...',
            allowOutsideClick: false,
            allowEscapeKey: false,
            showConfirmButton: false,
            theme: 'dark',
            didOpen: () => {
                // Cancel immediately if restored from browser history
                if (sessionStorage.getItem(SWEETALERT_HISTORY_RESTORED_KEY) === 'true') {
                    sessionStorage.removeItem(SWEETALERT_HISTORY_RESTORED_KEY);
                    Swal.close();
                    return;
                }

                Swal.showLoading();
                document.dispatchEvent(new CustomEvent('sweetalert:opened'));

                // Set timeout to auto-close if something hangs
                clearTimeout(swalTimeoutHandle);
                swalTimeoutHandle = setTimeout(() => {
                    if (Swal.isVisible()) {
                        console.warn('SweetAlert loading modal closed after timeout.');
                        closeSweetAlertLoader();
                    }
                }, SWEETALERT_TIMEOUT_MS);
            },
            didClose: () => {
                document.dispatchEvent(new CustomEvent('sweetalert:closed'));
                sessionStorage.removeItem(SWEETALERT_PATH_KEY);
                clearTimeout(swalTimeoutHandle);
                swalTimeoutHandle = null;
            }
        });
    }
}

//Register it
import { registerSweetAlertHxIndicator, showAlert } from './hx-sweetalert-indicator.js';
registerSweetAlertHxIndicator();
window.showAlert = showAlert;

Muistutuksena tästä käytetään path Avaimena on tietää, milloin hälytys pitää piilottaa.

HTMX

Viimeinkin käytämme htmx.ajax Esittääkseen pyynnön. Tämä on yksinkertainen GET-pyyntö uudelle URL-osoitteelle, jonka loimme päivitetyn kyselyjonon avulla.

   htmx.ajax('GET', newUrl, {
                target: el.dataset.target || el.getAttribute('hx-target') || 'body',
                swap: 'innerHTML',
                pushUrl: true
            });

Johtopäätöksenä

Tämä on yksinkertainen tapa selvittää URL-parametrit tunnisteavustimen ja alppi.js:n avulla. Sen avulla voit tyhjentää kaikki parametrit, tai vain tietyt, minimaalisella koodilla.

logo

©2024 Scott Galloway