I’m trying to create an “universal helper” to be used in my Svelte Kit app to be able in a SIMPLE way to persist in the URL the filter conditions of a dashboard or a list so that I can:
-
return to previous filter settings when I go back and to subsequent ones when I go forward with the browser keys or
-
save those filters (javascript simple objects with JSON.stringify()) in the browser bookmarks or as a link to share with some people.
I tried with this code (here the reproduction):
<script>
let { pagination = { page: 1, size: 10 }, condition = {} } = $props();
let listInput = $derived({
pagination: $state.snapshot(pagination),
condition: $state.snapshot(condition)
});
const players = $derived.by(() => {
return getData(listInput)
});
$effect(() => {
if (!!condition) {
const url = new URL(window.location.toString());
const paramCondition = url.searchParams.get('condition');
const actualCondition = JSON.stringify(condition);
if (paramCondition !== actualCondition) {
url.searchParams.set('condition', JSON.stringify(condition));
goto(url, { replaceState: false, noScroll: true, keepFocus: true });
}
}
});
afterNavigate(() => {
const url = new URL(window.location.toString());
const paramCondition = url.searchParams.get('condition');
if (paramCondition !== JSON.stringify(condition)) {
condition = JSON.parse(paramCondition || '{}');
}
});
</script>
and it works but I need to repeat the same code for each javascript object I need to save in the URL (not only condition
like in this example) and for each page.
Is there a way to make it “universal”?
I tried on a suggestion another way too:
function syncParams(params: Record<string, any | undefined>) {
const fromUrl = $derived($page.url.searchParams);
const retval = {};
for (let key in params) {
Object.defineProperty(retval, key, {
get() {
console.log('get, key:', key);
return fromUrl.get(key);
},
set(newVal) {
console.log('set, newVal:', newVal);
const url = new URL(window.location.toString());
url.searchParams.set(key, JSON.stringify(newVal));
goto(url, { replaceState: false, noScroll: true });
},
enumerable: true
});
}
return retval;
}
but it doesn’t work because my condition
can be {}
at first and the can be binded like:
let {
condition = params.condition,
} = $props();
<input type="text" bind:value={condition.name} />
I’m using Svelte 5 as you can see.
Can you hlep me understand how to do it?