Vue-router: Disable a component on some routes?

Created on 26 Nov 2015  路  9Comments  路  Source: vuejs/vue-router

Hello,

I'm not sure if this the correct way of thinking - but I want one of my components to be disabled or deactivated on some routes.

So here's my routes.

router.map({
    '/':                        { component: ProductsView },
    '/auth/login':              { component: LoginView },
    '/auth/register':           { component: RegisterView },
    '/products':                { component: ProductsView },
    '/products/:product':       { component: ProductView },
    '/categories':              { component: CategoriesView },
    '/categories/:category':    { component: CategoryView },
    '*':                        { component: NotFoundView }
});

My main template file looks like so:

<!DOCTYPE html>
<html lang="en" id="app">
    <head>
        <!-- Head Contents -->
    </head>
    <body>
        <header>
            <!-- Header Contents -->
            <navigation></navigation>
        </header>
        <div class="container">
            <router-view></router-view>
        </div>
    </body>
</html>

When I'm on either the /auth/login or /auth/register routes - I do not want my navigation component to appear.

How can I achieve this?

Most helpful comment

@JoeDawson I'm sure Vue provides many mechanisms to accomplish this. I believe the v-if or v-show directives should be used since this is a conditional rendering matter.

Now for the conditional expression to use with those directives you can utilize the $route.path or $route.name which are made available to each component by vue-router. This is documented here: http://vuejs.github.io/vue-router/en/route.html

First I would add names to my routes:

router.map({
    // ...
    '/auth/login': { name: 'login', component: LoginView },
    '/auth/register':  { name: 'register', component: RegisterView },
   // ...
});

Then you can just conditionally display the navigation based on the current route name:

<navigation v-if="['login', 'register'].indexOf($route.name) > -1"></navigation>

This is just one way, and I'm sure it can be cleaned up a bit. Though I would like to know if there is a potential _best practice_ way to do this since I imagine this is a common pattern.
Maybe @yyx990803 can enlighten us on the matter.

All 9 comments

@JoeDawson I'm sure Vue provides many mechanisms to accomplish this. I believe the v-if or v-show directives should be used since this is a conditional rendering matter.

Now for the conditional expression to use with those directives you can utilize the $route.path or $route.name which are made available to each component by vue-router. This is documented here: http://vuejs.github.io/vue-router/en/route.html

First I would add names to my routes:

router.map({
    // ...
    '/auth/login': { name: 'login', component: LoginView },
    '/auth/register':  { name: 'register', component: RegisterView },
   // ...
});

Then you can just conditionally display the navigation based on the current route name:

<navigation v-if="['login', 'register'].indexOf($route.name) > -1"></navigation>

This is just one way, and I'm sure it can be cleaned up a bit. Though I would like to know if there is a potential _best practice_ way to do this since I imagine this is a common pattern.
Maybe @yyx990803 can enlighten us on the matter.

@amirrustam I approached it a little differently in the end - I simply added a class to the body if the current route matched either /auth/login or /auth/register then used CSS to hide the component. Not the best solution I guess, but a working one.

<body :class="{ 'auth': $route.path==='/auth/register' || $route.path==='/auth/login' }">

Cool. is their a best practice to this, i couldn't find anything in the vue cookbook.

This will also work

<navigation v-if="['login', 'register'].includes($route.name)"></navigation>

What are the best practices for hiding/disabling a component on some routes?

In the nav component listen to the route changes to update a flag whether the nav will be shown or hidden, you may check with route name or path:

note: the following example uses typescript:

export const router = new Router({
  mode: "history",
  routes: [
    { name: "home", path: "/", component: Home },
    { name: "login", path: "/login", component: LoginView }
  ]
});
<nav v-if="showHeader">
...
</nav>
  @Watch("$route", { immediate: true })
  OnRouteChange(route: Route) {
    if (route.name == "login" || route.name == "signup") {
      this.showHeader = false;
    } else {
      this.showHeader = true;
    }
  }

Route meta fields provide yet another option:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      meta: { hideNavigation: true }
    }
  ]
})
<navigation v-if="!$route.meta.hideNavigation" />

This question covers a useful thing to know in general, however if you want to show/hide certain main components like a header or footer, the best way is to simply create multiple layouts that include the components you want.

Hide Header in some components using the current route path.

get current route path using this.$route.path

<navigation v-if="showNavigation"></navigation>
data() {
this.$route.path === '/' ? this.showNavigation = false : this.showNavigation = true
}
Was this page helpful?
0 / 5 - 0 ratings