Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Nuxt page selection

Basically I'm trying to either dynamically select a component for a matched route or have an internal rewrite so I can select a different route without changing url.

My solution right now: I have url's from an external resource I want to match, I'm catching these with a wildcard page in Nuxt using a _.js. In a middleware on this page I will determine the actual type of the page it should be (cmspage, productdetail, etc.) and place the result in the store. Then I would check if the data is found in the validate function so I can return a 404 if needed. If successful, would then use the render function to render components/pages/cms.vue or whatever type of page.

So this should work (still need most of the implementation) but it has the problem that I can't use a lot of Nuxt features (middleware, asyncData, fetch, validate, more?) that are available for pages which is exactly what I'm trying to achieve.

This nuxt config extension doesn't work but would be perfect:

{
  router: {
    extendRoutes(routes, resolve) {
      routes.push({
        path: '*',
        component: async () => {
          const pageType = 'pdp' // await getPageType()
          switch (pageType) {
            case 'cms':
              return resolve(__dirname, 'pages/cmsPage.vue')
            case 'pdp':
              return resolve(__dirname, 'pages/productDetailPage.vue')
            case 'plp':
              return resolve(__dirname, 'pages/productListPage.vue')
          }
        }
      })
    }
  }
}
like image 958
red-X Avatar asked Mar 24 '20 09:03

red-X


1 Answers

I am not fully sure if I get the question right, but I assume that:

  • You want one single path (route) for displaying different (dynamic) views
  • Before the route loads, you want to get the page type (probably from backend)
  • You don't want those components to be loaded to your application if they don't match the route

So if that's what you want, follow below:


  • Inside routes you need something like this:

let pageType = null;

export default new VueRouter({
  mode: "history",
  routes: [
    //... other routes
    {
      path: "/dynamic-page",
      component: () => import("./components/DynamicPage"),
      props: router => ({ pageType }),
      beforeEnter(to, from, next) {
        // getPageType() is supposed as a async method getting the page type
        getPageType().then(type => {
          pageType = type;
          next();
        });
      }
    }
  ]
});

So with the code above, we fetched the pageType and passed it to the component as a prop.

  • Next, create the dynamic component which should load different components
<template>
  <div class="dynamic-page">
    <component :is="pageType"/>
  </div>
</template>

<script>
export default {
  props: {
    pageType: String
  },

  components: {
    ProductList: () => import("../dynamic-pages/ProductListPage"),
    Cms: () => import("../dynamic-pages/CmsPage"),
    ProductDetail: () => import("../dynamic-pages/ProductDetailPage")
  }
};
</script>

So that component using lazy loading, will load only 1 component. And that is defined by pageType prop.

I made a CodeSandbox example

like image 152
Roland Avatar answered Oct 07 '22 19:10

Roland