Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Named router views

I'm building a Nuxt app with a layout that consists of 3/4 main content and 1/4 sidebar navigation that uses tabs that expand based on the current route.

My aim is to essentially have two router-views — one on the main page and one in each tab.

With the Vue Router I guess this would be possible to achieve via named views e.g.

<router-view name="rightSidebar"></router-view>

But obviously with Nuxt the idea is that the routing is taken care of behind the scenes...so it isn't possible to configure.

But none the less is it possible to use <NuxtPage /> in this way?

like image 638
Jack Avatar asked Oct 21 '25 04:10

Jack


2 Answers

I could find only one way to use named views with the NuxtPage component in Nuxt 3. You need to set up custom routes.

Add a file called app/router.options.ts in your project. (I don't know why it needs to be in a folder called app, other than that the docs say so.) Inside of that file, you can tweak the existing routes, and replace component: PageComponent with components: {default: PageComponent, foo: SomeComponent, bar: AnotherComponent}.

Examples below. Ask in the comments if you need more examples.

Example 1: Add a toolbar to a specific route:

import { RouterConfig } from "@nuxt/schema";

export default <RouterConfig>{
  routes: (routes) => {
    return routes
      .map((route) => {
        const name = String(route.name);

        if (name.startsWith("test-withToolbar")) {
          return {
            ...route,
            component: undefined,
            components: {
              default: route.component, // This is a component from the `pages` folder. Use it with `NuxtPage`.
              toolbar: () => import("~/toolbars/MyToolbar.vue"), // Use this with `NuxtPage(name="toolbar")`.
            },
          };
        }

        return route;
      });
  },
};

Then in app.vue (or in a layout file if you want to use layouts), you could have this template (I'm using Pug syntax instead of HTML for brevity):

div
  NuxtPage(name="toolbar")
  NuxtPage

Example 2: Add toolbars and footers automatically by path

Maybe we want to have a toolbars folder that behaves similarly to the pages folder. Then we could do something like this in app/router.options.ts:

import type { RouterConfig } from "@nuxt/schema";
import { readdirSync } from "fs";
import type { Component } from "@vue/runtime-core";

export default <RouterConfig>{
  routes: (routes) => {
    const toolbarNames = readdirSync("./toolbars").map((name) =>
      name.replace(/\.vue$/, "")
    );

    return routes.map((route) => {
      const name = String(route.name);

      if (!route.component) {
        return route;
      }

      const components: Record<string, Component> = {
        default: route.component,
      };

      if (toolbarNames.includes(name)) {
        components.toolbar = () => import(`~/toolbars/${name}.vue`);
      }

      return {
        ...route,
        component: undefined,
        components,
      };
    });
  },
};

This allows you to have a different toolbar on each page, while using the same layout, e.g.:

div
  NuxtPage(name="toolbar")
  NuxtPage

Example 3: Specify route components using page metadata

I had the idea of using the definePageMeta macro to add metadata to the components in the pages folder, and then use that in app/router.options.ts to add other components. However, it seems that definePageMeta is ignored or overwritten when app/router.options.ts is present. See https://github.com/nuxt/nuxt/discussions/19700 . If I figure out a way to do this, I will update this answer.

like image 174
rudolfbyker Avatar answered Oct 23 '25 04:10

rudolfbyker


In Nuxt3

For named router views...

The <NuxtPage> component has name prop; see Nuxt docs - NuxtPage. Presumably this could be useful if you have many router views.

<NuxtPage :name="myViewName" />

For named routes, use special meta...

In page meta, there are special reserved properties that invoke high-level adaptions. See Nuxt docs - Pages Special Metadata.

Set a name property in page meta:

pages/mypage.vue

definePageMeta({
    name: 'myCustomRouteName' // Gets passed to route object
    title: 'My Custom Page Title',
    
    // Custom meta like...
    myBreadcrumbTitle: 'Some Text Here' 
})

The route object will become like this:

{
    "name": "myCustomRouteName",
    "path": "mypage",
    "meta": {
      "title": "My Custom Page Title",
      "myBreadcrumbTitle": "Some Text Here"
    },
    "alias": []
}

And you can do stuff like:

Render <NuxtLink>'s by name...

<NuxtLink :to="{ name: 'myCustomRouteName'}">
    My link text
</NuxtLink>

... call the route programmatically...

function navigate(){
    return navigateTo({
        name: 'myCustomRouteName'
    })
}

or build a breadcrumb component, etc...

like image 23
MarsAndBack Avatar answered Oct 23 '25 05:10

MarsAndBack