Router
Ginjou can work with any router tool.
This layer gives Ginjou one shared router contract for navigation, path resolution, and current location state.
Router Context
Router context is the shared entry point for navigation and route state.
Interface
interface Router {
go: (params: RouterGoParams<any>) => void
back: () => void
resolve: (params: RouterGoParams<any>) => string
getLocation: () => RouterLocation<any>
onChangeLocation: (handler: (location: RouterLocation<any>) => void) => () => void
}
Methods
| Method | What it does |
|---|---|
go | Navigate to the next location. |
back | Move one step backward in router history. |
resolve | Convert route params into a final path string or href. |
getLocation | Return the current location snapshot. |
onChangeLocation | Subscribe to location changes and return a cleanup function. |
<script setup lang="ts">
import { defineRouterContext } from '@ginjou/vue'
import { createRouter } from '@ginjou/with-vue-router'
defineRouterContext(createRouter())
</script>
Navigate
useGo() is the low-level navigation helper.
It forwards one RouterGoParams object to the current router context.
If no router context exists, the helper becomes a safe no-op.
interface RouterGoParams<TMeta = unknown> {
to?: string
type?: 'push' | 'replace'
query?: Record<string, string | number | null | undefined>
hash?: string
keepHash?: boolean
keepQuery?: boolean
meta?: TMeta
}
| Property | Meaning |
|---|---|
to | The target path when you navigate by raw path. |
type | Choose push or replace. |
query | Query values for the next location. |
hash | Hash value for the next location. |
keepHash | Reuse the current hash when hash is not passed. |
keepQuery | Merge the current query into the next query before applying query. |
meta | Adapter-specific navigation options. |
With the official vue-router bridge, meta can carry vue-router route options such as named-route params.
keepQuery and keepHash reuse values from the current location. They do not create a second navigation step.
<script setup lang="ts">
import { useGo } from '@ginjou/vue'
const go = useGo()
function openPosts() {
go({
to: '/posts',
query: {
page: 2,
status: 'published',
},
keepHash: true,
})
}
function openPost(id: number) {
go({
meta: {
name: 'post-show',
params: { id },
},
})
}
</script>
<script lang="ts">
import { useGo } from '@ginjou/svelte'
const go = useGo()
function openPosts() {
go({
to: '/posts',
query: {
page: 2,
status: 'published',
},
keepHash: true,
})
}
function openPost(id: number) {
go({
meta: {
name: 'post-show',
params: { id },
},
})
}
</script>
Go Back
useBack() maps to router.back().
Use it when the page should follow the router history instead of targeting a new path.
If no router context exists, the helper becomes a safe no-op.
<script setup lang="ts">
import { useBack } from '@ginjou/vue'
const back = useBack()
</script>
<template>
<button type="button" @click="back()">
Back
</button>
</template>
<script lang="ts">
import { useBack } from '@ginjou/svelte'
const back = useBack()
</script>
<button type="button" onclick={back}>
Back
</button>
Current Location
useLocation() returns the current location as a reactive ref.
It starts from router.getLocation() and updates when the router context emits location changes.
interface RouterLocation<TMeta = unknown> {
path: string
params?: Record<string, string | string[]>
query?: Record<string, string | null | Array<string | null>>
hash?: string
meta?: TMeta
}
| Property | Meaning |
|---|---|
path | The current pathname. |
params | Decoded params extracted from the current path. |
query | The current query object. |
hash | The current hash value. |
meta | Adapter-specific parsed location metadata. |
<script setup lang="ts">
import { useLocation } from '@ginjou/vue'
import { computed } from 'vue'
const location = useLocation()
const currentPage = computed(() => location.value?.query?.page)
const currentId = computed(() => location.value?.params?.id)
</script>
<template>
<div>
<p>Path: {{ location?.path }}</p>
<p>Page: {{ currentPage }}</p>
<p>ID: {{ currentId }}</p>
</div>
</template>
<script lang="ts">
import { useLocation } from '@ginjou/svelte'
const location = useLocation()
const currentPage = $derived(location.value?.query?.page)
const currentId = $derived(location.value?.params?.id)
</script>
<div>
<p>Path: {location.value?.path}</p>
<p>Page: {currentPage}</p>
<p>ID: {currentId}</p>
</div>
Resolve Paths
useResolvePath() turns router params into a final path string.
It uses the same input shape as useGo(), but returns the resolved path instead of navigating.
This is useful for href values, custom links, previews, or anywhere else you need the final string before navigation.
<script setup lang="ts">
import { useResolvePath } from '@ginjou/vue'
import { computed } from 'vue'
const resolvePath = useResolvePath()
const postsHref = computed(() => resolvePath({
to: '/posts',
query: {
page: 2,
},
}))
const showHref = computed(() => resolvePath({
meta: {
name: 'post-show',
params: {
id: 42,
},
},
}))
</script>
<template>
<a :href="postsHref">Posts</a>
<a :href="showHref">Open Post</a>
</template>
<script lang="ts">
import { useResolvePath } from '@ginjou/svelte'
const resolvePath = useResolvePath()
const postsHref = $derived(resolvePath({
to: '/posts',
query: {
page: 2,
},
}))
const showHref = $derived(resolvePath({
meta: {
name: 'post-show',
params: {
id: 42,
},
},
}))
</script>
<a href={postsHref}>Posts</a>
<a href={showHref}>Open Post</a>
Unlike useGo() and useBack(), this helper throws when no router context is available.
Navigate by Resource Intent
useNavigateTo() combines router context with resource context.
Instead of passing a raw path every time, you can navigate by resource action and record id. If you pass plain router params, it falls back to the same low-level navigation flow as useGo().
| Input | Meaning |
|---|---|
RouterGoParams | Delegate directly to low-level router navigation. |
{ action: 'list', resource?, params? } | Build a resource path that does not need an id. |
{ action: 'create', resource?, params? } | Build a resource path that does not need an id. |
{ action: 'show', resource?, id, params? } | Build a resource path that needs an id. |
{ action: 'edit', resource?, id, params? } | Build a resource path that needs an id. |
false | Do nothing. |
When you create the helper with resource, later calls can omit the resource name.
<script setup lang="ts">
import { ResourceActionType } from '@ginjou/core'
import { useNavigateTo } from '@ginjou/vue'
const navigateTo = useNavigateTo({
resource: 'posts',
})
function openCreate() {
navigateTo({
action: ResourceActionType.Create,
})
}
function openPost(id: number) {
navigateTo({
action: ResourceActionType.Show,
id,
})
}
function cancel() {
navigateTo({
action: ResourceActionType.List,
params: {
page: 1,
},
})
}
</script>
<script lang="ts">
import { ResourceActionType } from '@ginjou/core'
import { useNavigateTo } from '@ginjou/svelte'
const navigateTo = useNavigateTo({
resource: 'posts',
})
function openCreate() {
navigateTo({
action: ResourceActionType.Create,
})
}
function openPost(id: number) {
navigateTo({
action: ResourceActionType.Show,
id,
})
}
function cancel() {
navigateTo({
action: ResourceActionType.List,
params: {
page: 1,
},
})
}
</script>
This helper is useful for redirects and controller-driven flows because it stays aligned with the resource definitions from the resource context.
Official Adapter
The repo currently includes two official router adapters.