1

So I'm trying to achieve a layout with optional sidebars based on the vue routes

Currently I have the following:

  1. an App.vue which has a MainLayout component with slots where I'm placing the router views
<main-layout>
    <template #main>
        <router-view/>
    </template>
    <template #sidebar>
        <router-view name="LeftSidebar"/>
    </template>
    <template #rightsidebar>
        <router-view name="RightSidebar"/>
    </template>
</main-layout>
  1. the router looking something like this:
const routes = [
  {
    path: "/lectures",
    components: {
      default: LectureList,
      LeftSidebar: MainMenu,
    }
  },
  {
    path: "/users",
    components: {
      default: UserList,
      LeftSidebar: MainMenu,
      RightSidebar: SomeOtherComponent
    }
  },
]
  1. the MainLayout.vue looking something like this (simplified)
<div>
    <div class="left-sidebar">
        <slot name="sidebar"/>
    </div>
    <div class="main">
        <slot/>
    </div>
    <div class="right-sidebar">
        <slot name="rightsidebar"/>
    </div>
</div>

Currently the main menu layout has a slot for the rightsidebar and I'd like it to render only if it has some content, ie if some route provides a component for the RightSidebar router view. I tried looking at the slots in MainLayout and add a v-if on the .right-sidebar div to only show if the slot for rightsidebar slot is present, but I guess it doesn't work since the router-view is present in there already

Any recommended way of dealing with this type of case?

Andrei S
  • 6,486
  • 5
  • 37
  • 54
  • Why can't you add the `v-if` to `template #rightSidebar` in App.vue? – stellr42 Nov 28 '22 at 15:11
  • Why not check in `App. vue` itself if the route has any component for the right sidebar or not? For example in `App. vue` we can check - `` – Neha Soni Nov 28 '22 at 15:14
  • maybe I'm doing it wrong, but adding `v-if="$route.components.RightSidebar"` yields an error "Cannot read properties of undefined (reading 'RightSidebar')" – Andrei S Nov 28 '22 at 15:26

1 Answers1

1

Using the matched property of the Vue router named views, we can check which props have been passed or not.

Here in the code, I added a watcher which will check for every route if props for sidebar views are passed or not and will update the data properties to used as the conditions.

<main-layout>
   <template #main>
      <router-view/>
   </template>
   <template #sidebar v-if="isLeftSideBar">
      <router-view name="LeftSidebar"/>
   </template>
   <template #rightsidebar v-if="isRightSideBar">
      <router-view name="RightSidebar"/>
   </template>
</main-layout>

<script >
export default {
    name: "App",
    data() {
        return {
            isLeftSideBar: false,
            isRightSideBar: false
        }
    },
    watch: {
        $route(to, from) {
            if (to.matched.length) {
                this.isLeftSideBar = to.matched[0].props.hasOwnProperty("LeftSidebar");
                this.isRightSideBar = to.matched[0].props.hasOwnProperty("RightSidebar");;
            }
        }
    },
} 
      
</script>

Please let me know if this works.

Neha Soni
  • 3,935
  • 2
  • 10
  • 32