| 1 | import type { Ref, WritableComputedRef } from "vue" |
| 2 | import type { SafeAny } from "@/types/utils" |
| 3 | import { onBeforeMount, watch } from "vue" |
| 4 | import { useRoute, useRouter } from "vue-router" |
| 5 | |
| 6 | /** |
| 7 | * Synchronizes a ref with a key in the query string parameters. |
| 8 | * @param key The query string key (e.g.: 'list_filters') |
| 9 | * @param ref The ref to synchronize |
| 10 | * @example |
| 11 | * ```ts |
| 12 | * useSyncUrlParams("list_filters", filters, { |
| 13 | * onMountCheck(found) { |
| 14 | * if (!found) { |
| 15 | * resetFilters() |
| 16 | * } |
| 17 | * } |
| 18 | * }) |
| 19 | * ``` |
| 20 | */ |
| 21 | export function useSyncUrlParams( |
| 22 | key: string, |
| 23 | ref: WritableComputedRef<SafeAny, SafeAny> | Ref<SafeAny>, |
| 24 | options?: { |
| 25 | onMountCheck: (found: boolean) => void |
| 26 | } |
| 27 | ) { |
| 28 | const route = useRoute() |
| 29 | const router = useRouter() |
| 30 | |
| 31 | // Update the query string when ref changes |
| 32 | watch( |
| 33 | ref, |
| 34 | val => { |
| 35 | router.replace({ query: { ...route.query, [key]: JSON.stringify(val) } }) |
| 36 | }, |
| 37 | { deep: true } |
| 38 | ) |
| 39 | |
| 40 | // On startup, if the query contains the key, update ref |
| 41 | onBeforeMount(() => { |
| 42 | if (route.query[key]) { |
| 43 | const param = route.query[key].toString() |
| 44 | const value = JSON.parse(`${param}`) |
| 45 | |
| 46 | if (value !== undefined) { |
| 47 | ref.value = value |
| 48 | } |
| 49 | |
| 50 | if (options?.onMountCheck && typeof options.onMountCheck === "function") { |
| 51 | options.onMountCheck(true) |
| 52 | } |
| 53 | } else if (options?.onMountCheck && typeof options.onMountCheck === "function") { |
| 54 | options.onMountCheck(false) |
| 55 | } |
| 56 | }) |
| 57 | } |