How to keep nested router views visible under a modal

128 views Asked by At

I have a problem on a Vue3 app.

I have a mainRouterView and a modalRouterView inside App.vue.
mainRouterView displays various stuff, including a child bottomRouterView, which displays all the main pages (Home, Page A, Page B, etc.).

I need to display modals above everything, inside modalRouterView, without hiding what's under. Modals can be triggered from any page.

Problem
When I open modals they show up correctly, mainRouterView and bottomRouterView are still here. But the content inside bottomRouterView disappears. Which means Home, Page A, Page B, etc.. aren't displayed anymore.

Question
How can I fix my code so that the bottomRouterView still displays its content (Home, Page A, Page B, etc.)? I think the problem comes from the line default: Main for the /modal route in my router, as in it's not specific enough.

Structure

App.vue/
├── modalRouterView/
│   ├── Modal A
│   ├── Modal B
│   └── ...
└── mainRouterView/
    └── bottomRouterView/
        ├── Home
        ├── Page A
        ├── Page B
        └── ...

Router

const routes = [
  {
    path: '/',
    component: Main,
    children: [
      {
        path: '',
        components: {
          bottomRouterView: Home,
        },
      },
      {
        path: 'page-a',
        components: {
          bottomRouterView: PageA,
        },
      },
      {
        path: 'page-b',
        components: {
          bottomRouterView: PageB,
        },
      },
    ],
  },
  {
    path: '/modal',
    components: {
      default: Main,
      modalRouterView: Modal,
    },
    props: true,
    meta: {
      showModal: true
    }
  },
];

Modal

<div v-if="showModal" class="modal-route">
  <div class="modal-content">
    <router-view name="modalRouterView"></router-view>
  </div>
</div>

mainRouterView which doesn't really have a name, I named it on my post so that it's more understandable

<router-view :key="$route.fullPath"></router-view>

Thank you for reading

1

There are 1 answers

0
AnnaGino On

I managed to fix the problem

I've given a name to the router in App.vue (don't think it changed anything, but it's clearer)

<router-view name="mainRouterView"></router-view>

And I've edited the router. I've moved the modal part as a child of root, and I've added a beforeEnter() to conditionally assign a component to bottomRouterView depending on the view we're coming from.

const routes = [
  {
    path: '/',
    components: {
      mainRouterView: Main,
    },
    children: [
      {
        path: '',
        name: 'home'
        components: {
          bottomRouterView: Home,
        },
      },
      {
        path: 'page-a',
        name: 'page-a'
        components: {
          bottomRouterView: PageA,
        },
      },
      {
        path: 'page-b',
        name: 'page-b'
        components: {
          bottomRouterView: PageB,
        },
      },
      {
        path: 'modal',
        name: 'modal',
        components: {
          mainRouterView: Main,
          bottomRouterView: null,
          modalRouterView: Modal,
        },
        props: true,
        meta: {
          showModal: true
        },
        beforeEnter: (to, from, next) => {
          const previousRoute = from.name;
          let componentForBottomRouterView;

          switch (previousRoute) {
            case 'home':
              componentForBottomRouterView = Home;
              break;
            case 'page-a':
              componentForBottomRouterView = PageA;
              break;
            case 'page-b':
              componentForBottomRouterView = PageB;
              break;
            default:
              componentForBottomRouterView = Home;
          }
          const bottomRouterViewRoute = to.matched.find(route => route.name === 'modal');
          if (bottomRouterViewRoute) {
            bottomRouterViewRoute.components.bottomRouterView = componentForBottomRouterView;
          }

          next();
        },
      },
    ],
  },
];