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

<datetime class="hidden">2025-04-25T23:00</datetime>

<!--category-- Javascript, HTMX, Alpine.js, ASP.NET Core -->
# Введение

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

[TOC]

# Проблема

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

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

```

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

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

1. В змозі очистити названий параметр
2. Я можу очистити список параметрів.
3. Можути очистити всі параметри
4. Відповісти про це HTMX
5. Використовуйте мій індикатор завантаження [мій індикатор навантаження](https://www.mostlylucid.net/blog/usingsweetalertforhxindicators).

# Рішення

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

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

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

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

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

```csharp
[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` іконка, яка дозволяє пользователю очистити всі параметри.

```html

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

```

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

```html

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

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

Чи навіть

```html

<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` атрибут. Це корисне, якщо ви хочете оновити певну частину сторінки з новим змістом

```html

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

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

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

```

### Результат

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

- Все:
  Таким чином ми отримуємо HTML з `x-all` атрибут і не `x-param` атрибут.

```html
<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` атрибут.

```html
<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` атрибут.

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

```javascript
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 індикатор навантаження, який я використовую в моєму проекті

Це трохи змінилося від [коли ми вперше побачили це](https://www.mostlylucid.net/blog/usingsweetalertforhxindicators). Тож я міг витягнути `showAlert` і зробити його доступним для зовнішніх модулів., які дозволяютьM SK1 мені використовувати його в обох `param-clearer` модуля і `hx-indicator` модуль.

```javascript
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, який ми створили з поновлюваним строком запиту

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

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

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