Back to "En Alpine.js och HTMX 'Klear söksträngparametern (sM SK3 taghelpare för ASPMSC4NET Core"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

Alpine.js ASP.NET Core HTMX Javascript

En Alpine.js och HTMX 'Klear söksträngparametern (sM SK3 taghelpare för ASPMSC4NET Core

Friday, 25 April 2025

Inleiding

Bara en snabb: , Jag hade ett behov i ett arbetsprojekt av att ha möjligheten att 'kla ut URL-parameter från en URL: n. This is useful when you have a URL with multiple parameters, and you want to remove one or more of them

Problemet

Mitt nuvarande projekt använder gamla urls.

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

Nu kan dessa variera med varje sida, så jag kan ha en BUNCHE i sidans URL och jag behöver kunna ta bort dem utan att skriva upp en massa boilerplattor för att göra det.

Du kan göra detta som en del av vilket inmatningskontroll du än använder så till exempel bredvid varje checkbox ( eller ett fint placeholder-stilt tydliga ikoner ) men och du kan använda den här tekniken även för de där.

  1. Att kunna avlägsna ett namnget parametr
  2. Att kunna lösa en lista av parametrar.
  3. Att kunna städa alla parametrar
  4. få det att skicka tillbaka med HTMX
  5. Ska den använda min laddande indikator min laddande indikator.

Lösningen

I mitt projekt använder jag redan

  • HTMX
  • Alpine.js
  • ASP.NET Core
  • TailwindCSS
  • DaisyUI

Så min lösning var fokuserad på att använda dessa för att få en trevlig utgångsbar funktionell lösning med minimal kod

Etikettbekymmern

Min TagHelper är ganska enkel, allt jag gör är att skapa en <a> tag med några attributer I' passerar senare in i Alpine Modulet och vi

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

Parameter

I användandet ser det ut som detta, först för 'klara alla parametrar '. Så jag tittar bara på Context.Request.Query om det finns några parametrar där så renderar jag den lilla x ikon för att låta användaren avlägsna alla parametrar.


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

Alternativt för namngeda parametrar kan jag göra detta


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

Vilket skulle förstås klargöra att den enda parametren

Eller till och med


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

Detta löser sedan alla namngeda parametrar från raden.

Den target attribut

Du har också möjligheten att gå igenom target attribut som kommer att användas som hx-target attribute. Detta är användbart om du vill uppdatera en specifik del av sidan med den nya innehållet


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

I mitt fall ( eftersom jag skrev det ) så valde jag målet som standard #page-content div.

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

Resultatet

De resulterar i att vi visar följande HTML:

  • Alla: Så vi får HTML med x-all attribut och inget x-param attribute.
<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>

  • Enkel Vi får HTML med x-param attribut och inget x-all attribute.
<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>
  • Multipla Vi får HTML med x-param attribut med en komma separat string och inget x-all attribute.
<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>

Var och en av dem har också de två alpina egenskaperna x-data och x-on:click.prevent som används för att installera Alpine-modulet och ropa på funktionen för att avgöra parametrerna.

Vi ska se hur det fungerar härnäst.

Alpine Modulet

Detta är förstås möjligt genom att använda Alpine.js för att konfigurera vår begäran och HTMX för att utföra den

Som ni kan se i koden härunder, har jag ett enkelt modul som tar path av den nuvarande sidan och använder sedan URL API för att analysera sökstringen ( du kan också skicka in en annan av någon anledning

Sedan tar vi elementet som klickats på och ser om det har x-all attribute; om det gör att vi löser alla parametrar från URL, annars delar vi upp x-param attribut med kommas och radera varenda en av dessa parametrar.

Sedan skapar vi en ny URL med den uppdaterade söktråden och använder HTMX för att göra ett begäran till den URL.

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;

Den showAlert funktionen med SweetAlert2

Du "'" kommer också märka att jag showAlert funktion. Det här är bara en enkel förpackning runt SweetAlert 2 laddande indikator som jag använder i mitt projekt

Det här är lite för twäckat från den sista gången vi såg det. Så jag kunde extrahera showAlert och göra den tillgänglig för externa moduler. som låter mig param-clearer modul och hx-indicator modul.

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;

Som en påminnelse använder detta path som nyckeln till att veta när man ska dölja larmet.

HTMX

Slutligen använder vi htmx.ajax att göra utmaningen. Det här är en enkel GET utmaning till den nya URL som vi skapade med den uppdaterade söksträngen

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

I slutsats

Det här är ett enkelt sätt att avlägsna URL-parameter med hjälp av en taghelpare och Alpine.

logo

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