Jony
Jony
NNuxt
Created by Kilisei on 1/22/2025 in #❓・help
Nuxt nested layout
For typescript to recognise the new PageMeta you need to add this to your env.d.ts:
declare module '#app' {
interface PageMeta {
/**
*
* NOTE: Due to how definePageMeta works the sidemenu is not allowed to reference variables from the script-setup block. Imports should work fine.
*/
sidemenu?: (options: { t: ReturnType<typeof useI18n>['t']; route: ReturnType<typeof useRoute> }) => SidemenuOptions;
}
}
declare module '#app' {
interface PageMeta {
/**
*
* NOTE: Due to how definePageMeta works the sidemenu is not allowed to reference variables from the script-setup block. Imports should work fine.
*/
sidemenu?: (options: { t: ReturnType<typeof useI18n>['t']; route: ReturnType<typeof useRoute> }) => SidemenuOptions;
}
}
Hope this helps! Feel free to ask if something is unclear! 🙂
12 replies
NNuxt
Created by Kilisei on 1/22/2025 in #❓・help
Nuxt nested layout
Hey, we ended up using definePageMeta, specifing a custom sidemenu Entry and using it in the Sidemenu-Component via the route.meta to retrive it. In the Sidemenu-Component:
const sidemenuOptions = ref<SidemenuOptions>();

const router = useRouter();
const route = useRoute();
const { t } = useI18n();

onServerPrefetch(updateSidemenu);
onBeforeMount(updateSidemenu);
watch(route, updateSidemenu);

/**
* Scans the current route and walks up the parents for a sidemenu definition in
* the Page Metadata and return it if found.
* @returns The sidebar definition or undefined if not found.
*/
function scanForSidemenu() {
let pathSegment = route.fullPath;
while (pathSegment.length > 0) {
const match = router.resolve(pathSegment);
if (match?.meta?.sidemenu) {
return match.meta.sidemenu;
}

const lastSlash = pathSegment.lastIndexOf('/');
if (lastSlash === -1) {
break;
}

pathSegment = pathSegment.substring(0, lastSlash).trim();
}
}

function updateSidemenu() {
const metaSidemenu = scanForSidemenu();
if (metaSidemenu) {
const sidemenu = typeof metaSidemenu === 'function' ? metaSidemenu({ t, route }) : metaSidemenu;
sidemenuOptions.value = sidemenu;
}
}
const sidemenuOptions = ref<SidemenuOptions>();

const router = useRouter();
const route = useRoute();
const { t } = useI18n();

onServerPrefetch(updateSidemenu);
onBeforeMount(updateSidemenu);
watch(route, updateSidemenu);

/**
* Scans the current route and walks up the parents for a sidemenu definition in
* the Page Metadata and return it if found.
* @returns The sidebar definition or undefined if not found.
*/
function scanForSidemenu() {
let pathSegment = route.fullPath;
while (pathSegment.length > 0) {
const match = router.resolve(pathSegment);
if (match?.meta?.sidemenu) {
return match.meta.sidemenu;
}

const lastSlash = pathSegment.lastIndexOf('/');
if (lastSlash === -1) {
break;
}

pathSegment = pathSegment.substring(0, lastSlash).trim();
}
}

function updateSidemenu() {
const metaSidemenu = scanForSidemenu();
if (metaSidemenu) {
const sidemenu = typeof metaSidemenu === 'function' ? metaSidemenu({ t, route }) : metaSidemenu;
sidemenuOptions.value = sidemenu;
}
}
In the Page wanting a Sidemenu:
definePageMeta({
sidemenu: ({ t }) => ({
// Whatever structure you want for your Sidemenu data
// ...
}),
});
definePageMeta({
sidemenu: ({ t }) => ({
// Whatever structure you want for your Sidemenu data
// ...
}),
});
12 replies