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
Juste un rapide, j'avais un besoin dans un projet de travail pour la capacité de « effacer » les paramètres d'URL d'une URL. Ceci est utile lorsque vous avez une URL avec plusieurs paramètres, et vous voulez supprimer un ou plusieurs d'entre eux (par exemple pour un filtre de recherche).
Mon projet actuel utilise des chaînes de requêtes d'anciennes écoles (c'est un site d'administration donc n'a pas besoin de la fantaisie des urls 'bien'). Donc je me retrouve avec une URL comme celle-ci:
/products?category=electronics&search=wireless+headphones&sort=price_desc&inStock=true&page=3
Maintenant, ils peuvent varier avec chaque page, de sorte que je peux finir avec un BUNCH dans l'URL de la page et je dois être en mesure de les effacer sans écrire un tas de plaque de chaudière pour le faire.
Vous pouvez le faire dans le cadre de tout contrôle d'entrée que vous utilisez ainsi par exemple à côté de chaque case à cocher (ou une icône claire de style de placeholder fantaisie) mais vous pouvez utiliser cette technique pour ceux aussi. Cependant, dans ce cas, je voulais faire deux choses principales:
Dans mon projet, j'utilise déjà
Ma solution était donc concentrée autour de l'utilisation de ceux-ci pour obtenir une solution agréable et fonctionnelle avec un code minimal.
Mon TagHelper est assez simple, tout ce que je fais est de créer un <a>
tag avec quelques attributs que je passerai plus tard dans le module alpin et nous avons terminé.
[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>");
}
}
Dans l'utilisation ceci ressemble à ceci, d'abord pour 'clairer tous les paramètres'. Donc, je regarde juste le Context.Request.Query
s'il y a des paramètres là-bas, je rends le petit x
icône pour laisser l'utilisateur effacer tous les paramètres.
@if(Context.Request.Query.Any())
{
<label class="param-label">
<clear-param all="true"></clear-param>
clear all
</label>
}
</div>
Alternativement pour les paramètres nommés, je peux le faire
<div class="param-label">
<clear-param name="myParam"></clear-param>
<p>My Param: @Model.MyParam</p>
</div>
Ce qui effacerait bien sûr ce paramètre unique.
Ou même
<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>
Cela efface alors tous les paramètres nommés de la chaîne.
target
attributYou ont également la possibilité de passer dans un target
l'attribut qui sera utilisé comme l'attribut hx-target
attribut. Ceci est utile si vous voulez mettre à jour une partie spécifique de la page avec le nouveau contenu.
<div class="param-label">
<clear-param name="myParam" target="#my-thing"></clear-param>
<p>My Param: @Model.MyParam</p>
</div>
Dans mon cas (parce que je l'ai écrit) j'ai par défaut la cible à mon #page-content
Div.
[HtmlAttributeName("target")]
public string Target { get; set; } = "#page-content";
Ces résultats donnent lieu au rendu du HTML suivant :
x-all
attribut et non x-param
attribut.<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
attribut et non x-all
attribut.<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
attribut avec une chaîne séparée par virgule et non x-all
attribut.<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>
Chacun d'eux a aussi les deux attributs alpins x-data
et x-on:click.prevent
qui sont utilisés pour configurer le module Alpine et appeler la fonction pour effacer les paramètres.
On va voir comment ça marche.
Ceci est bien sûr possible grâce à Alpine.js pour configurer notre demande et HTMX pour l'exécuter.
Comme vous pouvez le voir dans le code ci-dessous, j'ai un module simple qui prend le path
de la page actuelle, puis utilise URL
API pour analyser la chaîne de requête (vous pouvez également passer dans une autre pour quelque raison que ce soit :)).
On obtient alors l'élément qui a été cliqué et on vérifie s'il a le x-all
attribut; si nous supprimons tous les paramètres de l'URL, sinon nous avons divisé le x-param
attribut par virgules et supprimer chacun de ces paramètres.
Ensuite, nous créons une nouvelle URL avec la chaîne de requête mise à jour et utilisons HTMX pour faire une requête à cette 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
fonction utilisant SweetAlert2Vous noterez aussi que j'appelle showAlert
fonction. Ce n'est qu'un simple emballage autour de l'indicateur de chargement SweetAlert2 que j'utilise dans mon projet. Vous pouvez bien sûr remplacer cela par ce que vous voulez faire.»
Il s'agit là d'un phénomène légèrement modifié par rapport à l'année précédente. la dernière fois qu'on l'a vuC'est ce que j'ai dit. Pour que je puisse extraire le showAlert
de fonctionner et de le mettre à la disposition des modules externes. Ce qui me permet de l'utiliser dans les deux param-clearer
le module et le hx-indicator
module.
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;
Comme un rappel, il utilise le path
comme la clé pour savoir quand cacher l'alerte.
Enfin, nous utilisons htmx.ajax
de faire la demande. Il s'agit d'une simple requête GET à la nouvelle URL que nous avons créée avec la chaîne de requête mise à jour.
htmx.ajax('GET', newUrl, {
target: el.dataset.target || el.getAttribute('hx-target') || 'body',
swap: 'innerHTML',
pushUrl: true
});
Il s'agit d'une façon simple de effacer les paramètres d'URL à l'aide d'une balise helper et Alpine.js. Il vous permet d'effacer tous les paramètres, ou seulement ceux spécifiques, avec un code minimal.