NOTE: Apart from
(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
Solo uno veloce, ho avuto una necessità in un progetto di lavoro per la capacità di 'pulire' parametri URL da un URL. Questo è utile quando si dispone di un URL con più parametri, e si desidera rimuovere uno o più di essi (per esempio per un filtro di ricerca).
Il mio attuale progetto utilizza stringhe di query old-school (è un sito di amministrazione quindi non ha bisogno della fantasia di 'belle' urls). Quindi finisco con un URL come questo:
/products?category=electronics&search=wireless+headphones&sort=price_desc&inStock=true&page=3
Ora questi possono variare ad ogni pagina, così posso finire con un BUNCH nell'URL della pagina e ho bisogno di essere in grado di cancellarli senza scrivere un mazzo di piastra caldaia per farlo.
Si può fare questo come parte di qualsiasi controllo di input si utilizza così, ad esempio, accanto a ogni casella di controllo (o uno stile di segnaposto di fantasia icona chiara) ma e si può utilizzare questa tecnica per quelli troppo. Tuttavia, in questo caso volevo fare due cose principali:
Nel mio progetto uso già
Quindi la mia soluzione era focalizzata sull'utilizzo di questi per ottenere una bella soluzione funzionale con un codice minimo.
Il mio TagHelper è abbastanza semplice, tutto quello che faccio è creare un <a>
Tag con alcuni attributi Passerò più tardi nel Modulo Alpino e abbiamo finito.
[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>");
}
}
In uso questo sembra così, prima per 'chiarire tutti i parametri'. Quindi ho solo guardato il Context.Request.Query
Se ci sono dei parametri li'... Rendero' il piccolo... x
icona per consentire all'utente di cancellare tutti i parametri.
@if(Context.Request.Query.Any())
{
<label class="param-label">
<clear-param all="true"></clear-param>
clear all
</label>
}
</div>
Alternativamente per i parametri nominati posso fare questo
<div class="param-label">
<clear-param name="myParam"></clear-param>
<p>My Param: @Model.MyParam</p>
</div>
Il che, ovviamente, chiarirebbe quel singolo parametro.
O addirittura...
<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>
Questo cancella quindi tutti i parametri nominati dalla stringa.
target
attributoHai anche la possibilità di passare in un target
attributo che sarà utilizzato come hx-target
attributo. Questo è utile se si desidera aggiornare una parte specifica della pagina con i nuovi contenuti.
<div class="param-label">
<clear-param name="myParam" target="#my-thing"></clear-param>
<p>My Param: @Model.MyParam</p>
</div>
Nel mio caso (perché l'ho scritto) ho predefinito l'obiettivo al mio #page-content
Div.
[HtmlAttributeName("target")]
public string Target { get; set; } = "#page-content";
Questi risultano nel rendering del seguente HTML:
x-all
attributo e no x-param
attributo.<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>
x-param
attributo e no x-all
attributo.<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>
x-param
attributo con una stringa separata da virgola e no x-all
attributo.<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>
Ognuno di essi ha anche i due attributi alpini x-data
e x-on:click.prevent
che vengono utilizzati per impostare il modulo alpino e chiamare la funzione per cancellare i parametri.
Vedremo come funziona la prossima...
Questo è ovviamente reso possibile dall'utilizzo di Alpine.js per configurare la nostra richiesta e di HTMX per eseguirla.
Come potete vedere nel codice qui sotto, ho un semplice modulo che prende il path
della pagina corrente e poi utilizza la URL
API per analizzare la stringa di query (si potrebbe anche passare in un diverso per qualsiasi motivo:)).
Poi otteniamo l'elemento che è stato cliccato e controllare se ha il x-all
attributo; se lo fa cancelliamo tutti i parametri dall'URL, altrimenti dividiamo il x-param
attributo per virgole ed eliminare ciascuno di questi parametri.
Poi creiamo un nuovo URL con la stringa di query aggiornata e usiamo HTMX per fare una richiesta a quell'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
funzione utilizzando SweetAlert2Si noterà anche che io chiamo un showAlert
funzione. Questo è solo un semplice involucro intorno all'indicatore di carico SweetAlert2 che uso nel mio progetto. Ovviamente puoi sostituirlo con qualsiasi cosa tu voglia fare."
Questo è leggermente modificato dal L'ultima volta che l'abbiamo visto.. Cosi' potevo estrarre il showAlert
funzionare e metterlo a disposizione di moduli esterni. Che mi permette di usarlo in entrambi i param-clearer
il modulo e il hx-indicator
modulo.
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;
Come promemoria questo usa il path
come chiave per sapere quando nascondere l'allarme.
Infine, usiamo htmx.ajax
per fare la richiesta. Questa è una semplice richiesta GET al nuovo URL che abbiamo creato con la stringa di query aggiornata.
htmx.ajax('GET', newUrl, {
target: el.dataset.target || el.getAttribute('hx-target') || 'body',
swap: 'innerHTML',
pushUrl: true
});
Questo è un modo semplice per cancellare i parametri URL usando un tag helper e Alpine.js. Consente di cancellare tutti i parametri, o solo quelli specifici, con codice minimo.