ASP.NET 核心的Alpine.js和HTMX启用的 ASP.NET 标签助手 (中文 (Chinese Simplified))

ASP.NET 核心的Alpine.js和HTMX启用的 ASP.NET 标签助手

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

一. 导言 导言 导言 导言 导言 导言 一,导言 导言 导言 导言 导言 导言

简而言之,我需要一个工程项目 来“清除” URL 参数的能力 从 URL 中清除 URL 参数 。 当您有一个带多个参数的 URL 时, 并且您想要删除一个或多个参数( 例如搜索过滤器), 此选项是有用的 。

问题

我目前的计划使用旧式查询串(这是一个行政管理网站, 所以我最后有了像这样的 URL:

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

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

您可以将此作为您使用的任何输入控制的一部分, 例如在每个复选框旁边( 或一个花哨占位符样式清晰的图标), 但是您也可以使用此技术来控制 。 然而,在这种情况下,我想做两件事:

  1. 能够清除指定参数
  2. 能够清除参数列表 。
  3. 能够清除所有参数
  4. 和HTMX一起寄回去
  5. 使用我的装货指示器 我的装货指示器.

解决方案

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

  • HTMX
  • 阿尔卑山
  • ASP.NET核心
  • 尾风CSS
  • DisacyUI 调音界面

所以,我的解决方案是 专注于使用这些 以获得一个漂亮的 功能性解决方案 与最小代码。

标签辅助工具

我的TagHeelfer很简单 我所做的就是创造 <a> 带有几个属性的标记, 我稍后会传递到阿尔卑斯山模块, 我们就结束了 。

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

参数参数

使用这个看起来像这个, 首先是“ 清除所有参数 ” 。 所以我就看一看 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 属性属性

YOu还可以选择通过 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) 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-datax-on:click.prevent 用于设置阿尔卑斯山模块,并调用函数来清除参数。

我们看看接下来会怎样...

阿尔卑斯山模块

当然,之所以能够做到这一点,是因为利用Alpine.js来配置我们的请求和用于执行请求的HTMX。

从下面的代码中可以看到 我有一个简单的模块 path 当前页面,然后使用 URL API 用于分析查询字符串(您也可以因不同原因通过不同的查询字符串 :) 。

然后我们得到被点击的元素 并检查它是否拥有 x-all 属性;如果是的话,我们从 URL 中删除所有参数,否则我们分割 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 函数。 这只是一个简单的包装纸 围绕SweetAlert2 装载指标 我在我的项目中使用。 当然,你可以用任何你想做的事来代替它。"

这是略微调适的 我们最后一次看到它.. 这样我就能抽出 showAlert 功能,并提供给外部模块。 让我用它来 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 提出该请求。 这是对我们用更新查询字符串创建的新 URL 的简单 Get 请求 。

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

在结论结论中

这是使用标签助手和Alpine.js来清除 URL 参数的简单方法 。 它允许你清除所有参数, 或只是特定的参数, 使用最小代码。

logo

©2024 Scott Galloway