useRouteRecord
Loads the record a detail page's :id names, loads again when only the id changes, and tells you when there is nothing to show.
Import
ts
import { useRouteRecord } from '@shared/composables/useRouteRecord'Signature
ts
function useRouteRecord<Id>(
item: Ref<unknown>,
fetchOne: (id: Id) => Promise<void>,
): {
id: ComputedRef<Id>
notFound: ComputedRef<boolean>
}item and fetchOne are the pair useCrud returns, or any ref and loader of your own that fills it.
Returns
| Member | Type | Meaning |
|---|---|---|
id | ComputedRef<Id> | The current :id param. |
notFound | ComputedRef<boolean> | true once a load has finished and item is still empty. |
Example
vue
<script setup lang="ts">
import type { FieldDefinition } from '@core/schema/types'
import { useCrud } from '@core/crud/useCrud'
import DetailPageLayout from '@shared/components/common/pages/DetailPageLayout.vue'
import EmptyState from '@shared/components/feedback/EmptyState.vue'
import { useRouteRecord } from '@shared/composables/useRouteRecord'
import { computed } from 'vue'
interface Warehouse extends Record<string, unknown> {
id: string
name: string
city: string
}
const schema: FieldDefinition[] = [
{ key: 'name', type: 'text', label: 'Name', required: true },
{ key: 'city', type: 'text', label: 'City', required: true },
]
const { item, fetchOne } = useCrud<Warehouse>({
entity: 'warehouse',
baseUrl: '/warehouses',
schema,
})
const { notFound } = useRouteRecord<string>(item, fetchOne)
const title = computed(() => item.value?.name ?? '')
</script>
<template>
<DetailPageLayout :title="title">
<template #main>
<EmptyState
v-if="notFound"
:title="$t('common.recordNotFound')"
:description="$t('common.recordNotFoundHint')"
/>
<p v-else-if="item">
{{ item.city }}
</p>
</template>
</DetailPageLayout>
</template>Notes
- It loads again when only the id changes. vue-router reuses the page component when you go from
/projects/prj_1to/projects/prj_2, so a load inonMountedwould keep the first record on screen under the second address. This watches the param instead. - The old record is cleared first.
itemis set tonullbefore each load, so the page never shows one record under another record's address, even for a moment. - A 404 means not found. A 404 from the API, or an answer with an empty body, ends in
notFound. Any other error is thrown again, so your error handling still sees it. - Only its own route counts. When the reader leaves for another page that also has an
:id, the param changes before this page unmounts. The watcher ignores any route but the one the page was created on, so it does not fetch on the way out. - The last request wins. When the id changes twice quickly, only the newest load settles
notFound. - Forty-one detail pages in the demo modules use it. An unknown id shows "Record not found", with the edit and delete actions hidden.
Related
- useCrud — the
itemandfetchOneit takes. - Detail page layout — the page shell.
- Empty state — the not-found message.