5

Hi I have two templates:

  • The main site template, for normal pages with two bars in the sides: Main.vue
  • The error pages template, without bars on the sides for errors, like 404: 404.vue If user enters a normal page, the Main.vue template should be used, with nested routes for every page. If user enters an inexistent page, the 404.vue template with the error should be used. I Tryied following but it always shows 404 errors except on localhost:8080/ (root path access):

router.js:

export default new Router({
  mode: 'history',
  routes: [{
      path: '/',
      name: 'main',
      component: Main,
      childrens: [{
          path: '/',
          name: 'Home',
          components: {
            default: () =>
              import ('@/views/Home'),
            leftInfo: () =>
              import ('@/views/DashboardAdditionalInfo'),
            rightInfo: () =>
              import ('@/components/common/MyTicketsList')
          }
        },
        {
          path: 'dashboard',
          name: 'Dashboard',
          components: {
            default: () =>
              import ('@/views/Dashboard'),
            leftInfo: () =>
              import ('@/views/DashboardAdditionalInfo'),
            rightInfo: () =>
              import ('@/components/common/MyTicketsList')
          }
        }

      ]
    },

    {
      path: '*',
      name: '404',
      component: () =>
        import ('@/templates/404.vue')
    }
  ]
})

Any ideas on how to handle this scenario? Of course I can put the 404 handle inside the Main route, but that will show the two side bars.

jigarzon
  • 1,208
  • 2
  • 12
  • 28
  • 1
    Possible duplicate of [how to create a 404 component in vuejs using vue-router](https://stackoverflow.com/questions/45619407/how-to-create-a-404-component-in-vuejs-using-vue-router) – Jacob Goh Jul 06 '18 at 02:25
  • its not the same case, because there is no need to use different templates on that post. But its ok, the only way to make it work I found is that – jigarzon Jul 06 '18 at 18:48

1 Answers1

5

You could use the dynamic layouts approach from the shards ui vue template. It essentially wraps your app level <router-view/> in the correct layout component depending on an optional meta-tag you give your routes in router.js.

App.vue:

<template>
  <div id="app">
    <component :is="layout">
      <router-view/>
    </component>
  </div>
</template>

<script>
export default {
    name: 'app',
    computed: {
      layout() {
        // none-layout will be used if the meta.layout tag is not set
        // computed may not be best place in vue lifecycle for this but it works ok
        return `${this.$route.meta.layout || 'none'}-layout`;
      }
    }
}
</script>

router.js:

import Vue from "vue";
import Router from "vue-router";
import Errors from "./views/Errors.vue";
Vue.use(Router);

export default new Router({
    mode: 'history',
    routes: [
        {
            path: "/",
            name: "dash",
            component: () => import('./views/Dashboard.vue'),
            meta: { layout: 'default-dash' }
        },
        {
            path: '/signup',
            component: () => import('./views/Signup.vue'),
            // meta.layout tag not present so 'none' will be used
        },
        {
            path: '*',
            component: Errors,
            meta: { layout: 'none' }
        }
    ]
});

main.js:

import Vue from 'vue'
import App from './App.vue'
import router from "./router";

// Layouts
import DefaultDash from '@/layouts/DefaultDash.vue';
import None from '@/layouts/None.vue';

// Layouts as usable components
Vue.component('default-dash-layout', DefaultDash);
Vue.component('none-layout', None);

Vue.config.productionTip = false

new Vue({
    router,
    render: h => h(App),
}).$mount('#app')

DefaultDash.vue:

<template>
    <div>
        <NavBar/>
        <SideBar/>
        <slot/>
    </div>
</template>

<script>
import NavBar from "../components/NavBar";
import SideBar from "../components/SideBar";

export default {
  name: "default-dash",
  components: { NavBar, SideBar }
};
</script>

None.vue:

<template>
    <div>
        <slot/>
    </div>
</template>

<script>
export default {
  name: "none"
};
</script>

Now your vue 404 errors will load without any sidebar or navbar. You can encapsulate all your main content pages within whatever outer layout you want and all you have to do is specify which template to use in a meta tag.

Ad Hero
  • 51
  • 1
  • 2