Альпіний.js і HTMX 'Parameter прозорих строків zapytaньM SK2sMSC3 вказівник на тег для ASP .NET Core (Українська (Ukrainian))

Альпіний.js і HTMX 'Parameter прозорих строків zapytaньM SK2sMSC3 вказівник на тег для ASP .NET Core

Friday, 25 April 2025

//

7 minute read

Введение

Просто один швидкий , У моєму проекті була потреба в здатності відокремлювати параметри URL з URL 'clear МSK2 Це корисно, коли у вас є URL із багатьма параметрами МSK4 і ви хочете видалити один або більше з них

Проблема

Мій теперішній проект використовує старі-стрічки запитів школи M SK1it' це адміністративна веб-страна, тому не потребує ' модності МSK4 гарно МSK5 urlsMSC6 Тож я закінчу з таким URL

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

Тепер вони можуть змінюватися з кожним листом, так що я можу закінчити з BUNCH в URL сторінки і мені потрібно бути в змозі очистити їх, не пишучи купу котла для цього.

Ви можете зробити це як частину будь-якого управління входом, яке ви використовуєте, наприклад, поруч з кожним чекбоксом ( або у стилі фешенебельного placeholder прочистити значок ) але ви можете використовувати цю техніку і для тих, хто теж займається цим МSK2 Однак МSK3 в цьому випадку я хотів зробити дві головні речі

  1. В змозі очистити названий параметр
  2. Я можу очистити список параметрів.
  3. Можути очистити всі параметри
  4. Відповісти про це HTMX
  5. Використовуйте мій індикатор завантаження мій індикатор навантаження.

Рішення

У своєму проекті я вже користуюся

  • HTMX
  • Alpine.js
  • ASP.NET Кора
  • TailwindCSS
  • DaisyUI

Отже, моє рішення було спрямоване на використання цих приладів для отримання гарного вигляду

Допомічник тагов

Мій TagHelper досить простий, все, що я роблю - це створити <a> ярлик з декількома атрибутами Я' пізніше перейду до Альпіського модуля і миM SK1 закінчимо

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

Параметри

У використанні це виглядає так: , спочатку для ' розібратися з усіма параметрами МSK2 Я просто дивлюся на Context.Request.Query якщо там є якісь параметри, я відтворюю маленьку x іконка, яка дозволяє пользователю очистити всі параметри.


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

Альтернативно для названих параметрів я можу зробити це


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

Це зрозуміло, що один із параметрів - .

Чи навіть


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

Таким чином, всі названі параметри відокремлені від строку.

І target властивість

У вас також є можливість пройти target атрибут, який буде використаний як hx-target атрибут. Це корисне, якщо ви хочете оновити певну частину сторінки з новим змістом


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

У моєму випадку ( тому, що я написав це ) Я за замовчанням встановив ціль для мого #page-content div.

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

Результат

В результаті отримуємо ось такий HTML:

  • Все: Таким чином ми отримуємо HTML з x-all атрибут і не x-param атрибут.
<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>

  • Одинакова Ми отримуємо HTML з x-param атрибут і не x-all атрибут.
<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>
  • Кілька Ми отримуємо HTML з x-param атрибут із відокремленим символом і без x-all атрибут.
<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>

Кожна з них також має дві альпійські риси x-data і x-on:click.prevent які використовують для налаштування модуля Альпі та викликають функцію, щоб очистити параметри.

Ми подивимось, як це працює далі.

Альпійський модуль

Це, звісно ж, стало можливим, використовуючи Alpine.js для конфігурації нашого запиту і HTMX для його виконання

Як ви бачите в коді нижче, Я маю простий модуль, який бере path і потім використовує URL API для аналізу строку запиту ( ви також можете пройти в іншому з будь-якої причини :)) МSK2

Потім ми отримуємо елемент, який був натиснутий і перевіряємо, чи він має x-all атрибут; якщо ми видаляємо всі параметри з URLM SK1 інакше ми розділяємо x-param і видалити кожен із цих параметрів.

Далі ми створюємо новий URL з поновлюваним строком запиту і використовуємо HTMX, щоб запросити цей 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;

І showAlert функція, яка використовує SweetAlert2

Ви також зауважите, що я називаю showAlert функція. Це просто простий упаковник навколо SweetAlert 2 індикатор навантаження, який я використовую в моєму проекті

Це трохи змінилося від коли ми вперше побачили це. Тож я міг витягнути showAlert і зробити його доступним для зовнішніх модулів., які дозволяютьM SK1 мені використовувати його в обох param-clearer модуля і hx-indicator модуль.

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;

Як нагадування це використовує path як ключ, щоб знати, коли приховати попередження.

HTMX

Нарешті, ми використовуємо htmx.ajax для створення запиту. Це простий запрос GET до нового URL, який ми створили з поновлюваним строком запиту

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

На завершення

Це простий спосіб очистити URL-параметри, використовуючи вказівник та Альпіний.

Finding related posts...
logo

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