Skip to content

Commit

Permalink
chore: add route.from property to RouterView::route (#2872)
Browse files Browse the repository at this point in the history
Adds the ability to inspect the `route` of the previous page, i.e. the history using `RouteView::route.from`.

This is useful for if we need to take the user to a certain page depending on where they came from.

---

We could use native `location.history` to do things like this, but it doesn't give you Vue route information.

The downside is here, we only store the single previous page, i.e. where you came from not the full history. This feels like Vue more seeing as Vue only works with the idea of `from`.

I doubt we'll need to store a full history of routes for anything, so this is fine for the moment. If we ever need to store a full history we can do that under `route.history`, and keep `route.from` as a shortcut to `route.history[0]`.

---

I also changed some naming inside RouteView here. RouteViews are nested so all of them haveParents apart from the top one (i.e. the root RouteView), and only the root RouteView doesn't have a root 🤯 .

The implementation just tracks all route changes in the root RouteView (the one that is always on the page) using Vue's `route.beforeEach` callback, and all child routes then read from the property we keep up-to-date using this callback (`route.from`).

---

Signed-off-by: John Cowen <[email protected]>
  • Loading branch information
johncowen authored Oct 10, 2024
1 parent ff7b2e6 commit 907bdc7
Showing 1 changed file with 27 additions and 8 deletions.
35 changes: 27 additions & 8 deletions src/app/application/components/route-view/RouteView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:data-testid="name"
>
<div
v-if="!hasParent"
v-if="!hasRoot"
id="application-route-announcer"
ref="title"
class="route-view-title visually-hidden"
Expand Down Expand Up @@ -46,6 +46,7 @@
back: routerBack,
children,
child,
from,
}"
/>
</DataSource>
Expand All @@ -69,10 +70,12 @@ import DataSink from '../data-source/DataSink.vue'
import DataSource from '../data-source/DataSource.vue'
import { useUri } from '@/app/application/services/data-source'
import { sources } from '@/app/me/sources'
import type { RouteRecordRaw } from 'vue-router'
import type { Ref } from 'vue'
import type { RouteRecordRaw, RouteLocationNormalizedLoaded } from 'vue-router'
export type RouteView = {
name: string
from: Ref
addTitle: (item: string, sym: Symbol) => void
removeTitle: (sym: Symbol) => void
addAttrs: (item: Partial<Record<string, string>>, sym: Symbol) => void
Expand Down Expand Up @@ -118,12 +121,13 @@ class UniqueId {
return uniqueId(props.name)
}
}
const name = computed(() => props.name)
const name = computed(() => props.name)
const submit = ref((_args: any) => {})
const title = ref<HTMLDivElement | null>(null)
const titles = new Map<Symbol, string>()
const attributes = new Map<Symbol, SupportedAttrs>()
const from = ref<RouteLocationNormalizedLoaded | undefined>()
const joinTitle = (titles: string[]) => {
return titles.reverse().concat(t('components.route-view.title', { name: t('common.product.name') })).join(' | ')
Expand All @@ -139,6 +143,7 @@ const child = () => {
const routeView = {
name: props.name,
from,
addTitle: (item: string, sym: Symbol) => {
const $title = title.value
if ($title) {
Expand Down Expand Up @@ -238,22 +243,36 @@ const routerBack = (...args: RouteReplaceParams) => {
routeReplace(...args)
}
const hasParent: RouteView | undefined = inject(ROUTE_VIEW_ROOT, undefined)
if (!hasParent) {
const hasRoot: RouteView | undefined = inject(ROUTE_VIEW_ROOT, undefined)
if (!hasRoot) {
// use the default title if we are the topmost RouteView
setTitle(t('components.route-view.title', { name: t('common.product.name') }))
// listen for to our navigations so we can set route.from
router.beforeEach((_to, f) => {
from.value = f
return true
})
// add the root so all other RouteView are marked as children
provide(ROUTE_VIEW_ROOT, routeView)
}
// add RouteTitle's parent
provide(ROUTE_VIEW_PARENT, routeView)
const parent: RouteView = hasParent || routeView
//
const root: RouteView = hasRoot || routeView
watch(() => props.attrs, (attrs) => {
if (Object.keys(attrs).length > 0) {
parent.addAttrs(attrs, sym)
root.addAttrs(attrs, sym)
}
}, { immediate: true })
if (hasRoot) {
watch(() => root.from, (val) => {
from.value = val.value
}, { immediate: true })
}
onBeforeUnmount(() => {
parent.removeAttrs(sym)
root.removeAttrs(sym)
})
</script>

0 comments on commit 907bdc7

Please sign in to comment.