This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Απλά μια γρήγορη, είχα ανάγκη σε ένα έργο εργασίας για την ικανότητα να "καθαρίσει" παραμέτρους URL από ένα URL. Αυτό είναι χρήσιμο όταν έχετε ένα URL με πολλαπλές παραμέτρους, και θέλετε να αφαιρέσετε ένα ή περισσότερα από αυτά (για παράδειγμα ένα φίλτρο αναζήτησης).
Το τρέχον πρότζεκτ μου χρησιμοποιεί παλιάς σχολής συμβολοσειρές ερωτημάτων (είναι ένας δικτυακός τόπος διαχείρισης, οπότε δεν χρειάζεται τη φαντασία των "καλών" URLs). Οπότε καταλήγω με ένα URL σαν αυτό:
/products?category=electronics&search=wireless+headphones&sort=price_desc&inStock=true&page=3
Τώρα αυτά μπορούν να διαφέρουν με κάθε σελίδα, έτσι μπορώ να καταλήξω με ένα BUNCH στη σελίδα URL και πρέπει να είμαι σε θέση να τους καθαρίσει χωρίς να γράψετε ένα μάτσο λεβητοστάσιο για να το κάνουμε.
Μπορείτε να το κάνετε αυτό ως μέρος του οποιουδήποτε ελέγχου εισόδου που χρησιμοποιείτε έτσι για παράδειγμα δίπλα σε κάθε κουτί ελέγχου (ή ένα φανταχτερό στυλ placeholder σαφές εικονίδιο) αλλά μπορείτε να χρησιμοποιήσετε αυτή την τεχνική και για εκείνους επίσης. Ωστόσο, σε αυτή την περίπτωση ήθελα να κάνω δύο βασικά πράγματα:
Στο πρόγραμμά μου χρησιμοποιώ ήδη
Έτσι, η λύση μου ήταν συγκεντρωμένη γύρω από τη χρήση αυτών για να πάρει μια όμορφη, λειτουργική λύση με ελάχιστο κώδικα.
Το TagHelper μου είναι αρκετά απλό, το μόνο που κάνω είναι να δημιουργήσω ένα <a>
Ετικέτα με μερικά χαρακτηριστικά που θα περάσω αργότερα στην Alpine Module και τελειώσαμε.
[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.
[HtmlAttributeName("target")]
public string Target { get; set; } = "#page-content";
Αυτά έχουν ως αποτέλεσμα την απόδοση της ακόλουθης 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>
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>
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-data
και x-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 που χρησιμοποιώ στο έργο μου. Μπορείτε φυσικά να το αντικαταστήσετε αυτό με ό,τι θέλετε να κάνετε."
Αυτό είναι ελαφρώς tweaked από το Την τελευταία φορά που το είδαμε. Για να μπορέσω να βγάλω το... showAlert
να λειτουργεί και να το καθιστά διαθέσιμο σε εξωτερικές ενότητες. Το οποίο ας το χρησιμοποιήσω και στα δύο. param-clearer
ενότητα και 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;
Ως υπενθύμιση αυτό χρησιμοποιεί το path
ως το κλειδί για να ξέρετε πότε να κρύψετε τον συναγερμό.
Τέλος, χρησιμοποιούμε htmx.ajax
να υποβάλει το αίτημα. Αυτό είναι ένα απλό αίτημα GET στο νέο URL που δημιουργήσαμε με την ενημερωμένη συμβολοσειρά ερώτημα.
htmx.ajax('GET', newUrl, {
target: el.dataset.target || el.getAttribute('hx-target') || 'body',
swap: 'innerHTML',
pushUrl: true
});
Αυτός είναι ένας απλός τρόπος για να καθαρίσετε τις παραμέτρους URL χρησιμοποιώντας έναν βοηθό ετικετών και Alpine.js. Σας επιτρέπει να καθαρίσετε όλες τις παραμέτρους, ή μόνο συγκεκριμένες, με ελάχιστο κωδικό.