# Alpine.js 和 HTMX @ 'Clear 查询字符串参数@(sMS K3} ASP.NET 核心标记助手

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

<!--category-- Javascript, HTMX, Alpine.js, ASP.NET Core -->
# 一. 导言导言 导言 导言 导言

快速的 @ , @ 我在一个工作工程中需要能够从 URL MS K3} <% 1 clear ' > < URAL 参数的能力 < ' n> 。 如果您有一个具有多个参数的 URR _,, 您想要删除其中的一个或数个 {(} a working project for a complication to 'MSK1\" clecreen < MPK2\ > URl 参数, 这将有用, 例如搜索过滤器@).}

[TOC]

# 问题

我目前的计划使用旧的“-”学校查询字符串 “(”“it'”是一个管理网站,所以“MS K3”是否需要 '“nicke”'“urls@).”这样的快递功能呢?

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

```

现在,这些可以随每页而变化 ,}这样我就能在网页 URL 中找到一个 BUNCH了 我需要能够清除它们 而不用写一堆锅炉板来完成它

您可以将此作为您所使用的任何输入控制的一部分, 举例来说, 每个复选框旁边的“ (” 或者一个花哨占位符样式清除图标@ MS K1} {但您可以使用此技术来对付那些太过关.}(然而)%,}在这种情况下我想做两件主要的事情_ :}

1. 能够清除指定参数
2. 能够清除参数列表@. @%
3. 能够清除所有参数
4. 和HTMX一起寄回去
5. 使用我的装货指示器 [我的装货指示器](https://www.mostlylucid.net/blog/usingsweetalertforhxindicators).

# 解决方案

在我的项目中,我已经使用

- HTMX
- 阿尔卑斯山
- ASP=.NET核心
- 尾风CSS
- DisayUI 调音界面

所以,我的解决方案是 专注于使用这些来获得一个好看的功能解决方案 用最起码的代码.

## 标签辅助工具

我的TagHelfer非常简单 我所做的就是创造一个 `<a>` 带有一些属性的标记 I'}Lall 稍后会传递到阿尔卑斯山模块中, weMS K1}{re done}\ .}

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

### 参数

在使用中, 这看起来像这个“ , @ ” 首先为 “ ' @ clear all 参数@ MS K2} @ 所以我就看看 `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` 属性属性

YOu还可以选择通过 `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` {\fn黑体\fs22\bord1\shad0\3aHBE\4aH00\fscx67\fscy66\2cHFFFFFF\3cH808080}我...

```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来实施该请求和 HTMX@.

正如您在下面的代码“MSMK0”中看到的那样,我有一个简单的模块来使用 `path` 当前页面,然后使用 `URL` 用于解析查询字符串“(”的API,您也可以因不同的原因通过不同的查询字串 “:))”和“MSSK2”

然后我们得到被点击的元素 并检查它是否拥有 `x-all` 属性@;}如果从 URL ,}我们删除了所有参数,否则可以分割 `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` 函数 SweetAlert\2

你也会注意到,我叫 `showAlert` 函数@.}这仅仅是在我的项目中 SweetAlert2}装入指示器我使用的SweetAlert.}你当然可以用您想要做什么来取代它

这是略微调适的 [我们最后一次看到它](https://www.mostlylucid.net/blog/usingsweetalertforhxindicators).#所以我可以提取 `showAlert` 功能,并提供给外部模块@. @} `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` 来请求\.}这是对我们用更新的查询字符串创建的新 URL的一个简单的 Get 请求@ . {}

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

# 在结论中的结论

这是使用标签助手和 Alpine 辅助器及Alpine @ . @js.}来清除 URL 参数的简单方法。 它允许您以最小代码@ MS K4}来清理所有参数@ MPK2{ 或仅特定参数@,}