Lesson 18 / 25

Nested Routes and Route Meta

Layouts and per-route information.

Children and meta fields

A route can have children: the parent component renders the shared layout plus its own <RouterView />, where the matched child appears. This suits dashboards and settings areas with a common sidebar. A child with an empty path '' is shown at the parent URL. Each route can carry a meta object with arbitrary information, such as requiresAuth or a page title. Guards read to.meta, which merges meta from the parent and child records, so marking a parent as requiresAuth protects all its children. With TypeScript you can type meta fields by augmenting the RouteMeta interface.

A protected dashboard layout

Nested routes plus a meta-based guard.

const routes = [
  {
    path: '/dashboard',
    component: () => import('@/layouts/DashboardLayout.vue'), // contains <RouterView />
    meta: { requiresAuth: true },
    children: [
      { path: '', name: 'dashboard', component: () => import('@/views/DashOverview.vue') },
      { path: 'reports', component: () => import('@/views/DashReports.vue'),
        meta: { title: 'Reports' } },
      { path: 'admin', component: () => import('@/views/DashAdmin.vue'),
        meta: { roles: ['admin'] } },
    ],
  },
]

router.beforeEach((to) => {
  const auth = useAuthStore()          // a Pinia store, see section 7
  if (to.meta.requiresAuth && !auth.isLoggedIn) return { name: 'login' }
  if (to.meta.roles && !to.meta.roles.includes(auth.role)) return { name: 'dashboard' }
})

router.afterEach((to) => {
  document.title = to.meta.title ?? 'My App'
})

Rooms inside a wing

A nested route is a wing of a building: one entrance with shared corridors (the layout), and individual rooms (child routes) inside it. Lock the wing door (meta on the parent) and every room is protected.

Quick check: Where does a child route component render?

  • In the RouterView inside the parent route's component
  • Always in the RouterView of App.vue
  • In a new browser tab
  • Nowhere until it is registered globally
Answer

In the RouterView inside the parent route's component — Each level of nesting needs its own RouterView.