Skip to content
Advertisement

Dynamic Routing for Dynamic Components in Vue3

A dynamic component with Dynamic Routing is needed for me in Vue3. I wanted to render the component which is coming from the params (path named id) from the router.ts

As you can see here in router.ts I have a dynamic parameter named as id. I wanted the same component to be rendered with the same name.

For example: If http://localhost:3000/forms/form/FirstPage is entered it should render the FirstPage component which I had already created in my project.

and when http://localhost:3000/forms/form/SecondPage is entered it should render the SecondPage component and so on…

My question is how to do it I have tried multiple ways and one of the ways is like that:

  {
    path: "/forms/form/:id",
    component: () => import("../pages/" + location.pathname.slice(1) + ".vue")
  },

But it is not working. Below I have also shared my App.vue and router/index.ts code

  1. This is my router/index.ts file
import { createWebHistory, createRouter, useRoute } from "vue-router"
import FirstPage from "../pages/FirstPage.vue"
import SecondPage from "../pages/SecondPage.vue"
import ThirdPage from "../pages/ThirdPage.vue"
import NotFound from "../components/NotFound.vue"
const routes = [
  {
    path: "/",
    name: "first",
    component: FirstPage
  },
  {
    path: "/2/70",
    name: "second",
    component: SecondPage
  },
  {
    path: "/3/70",
    name: "third",
    component: ThirdPage
  },
  {
    path: "/forms/form/:id",
    component: () => import("../pages/" + location.pathname.slice(1) + ".vue")
  },
  {
    path: "/:catchAll(.*)",
    component: NotFound
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

  1. App.vue file
<template>
  <router-view></router-view>
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>router/index.ts file

Advertisement

Answer

location.pathname isn’t generally supposed to be accessed directly in Vue router. It shouldn’t be accessed at the point when route component is resolved because the location isn’t changed yet.

Dynamic component can be wrapped with another component:

  {
    path: "/semanux/form/:id",
    component: FormWrapperPage,
  },

Where wrapper component is something like:

<component :is="PageComp"/>

...

const route = useRoute();
const PageComp = ref();

watch(
  () => route.params.id,
  async id => {
    try {
      PageComp.value = (await import("../pages/" + id + ".vue")).default
    } catch {
       router.push('/404')
    }
  },
  { immediate: true }
)

Since dynamic component is rendered after navigation, missing components need to be handled manually.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement