Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue render component as modal in specific route if route metadata key is set to true

I'm using vue-router and i'm trying to create a functionality as follows:

I want to be able to specify in the router routes if a component should be rendered in modal or not. And if it is rendered in Modal keep every component below ( under modal-mask ) as it was. I've created a modal-wrapper component that have basic modal structure and slot inside its modal body so the component I want to render should go in the slot. But how to achieve that. Does Vue-Router have options for that functioanlity.

Router routes:

{
  path: '/customers/:clientId',
  component: customerView
  meta: {
    auth: true,
  },
},
{
  path: '/customers/:clientId/addAddress',
  component: dataViewAdd
  meta: {
    openInModal: true,
    auth: true,
  },
},

Since if component should be rendered inside modal while overlaying the previous router-view, I guess ill need 2 router-views.

<router-view class="normal-view"></router-view>
<router-view class="modal-view" name="modal-view"></router-view>
like image 394
Georgi Antonov Avatar asked Sep 20 '25 22:09

Georgi Antonov


1 Answers

If the component displayed in each modal route was not used in a non-modal context, then you can just modify the modal route component's template (dataViewAdd) so that the modal component is the root of the template. But you mentioned that you would be reusing these components in different situations (so one route might use dataViewAdd inside a modal and another route might use dataViewAdd not inside a modal).

You could create wrapper modal versions of each component, but that'll become messy; it looks like you just want to be able to specify openInModal: true and have it work for any component.

You also mentioned that the position of the modal in the DOM doesn't matter (otherwise I'd recommend using something like portal-vue to assist with this).

First you'll need to change your router configuration so that the modal route is a child of the component you want to keep visible underneath it. Make sure customerView has a <router-view> inside it.

Create a helper function which returns a modal-wrapped version of the component and use that as the route component. This doesn't use the openInModal meta property, but it works in a similar way.

The following code is untested.

import Modal from './modal.vue';

function wrapInsideModal(childComponent) {
  return {
    functional: true,
    render(h) {
      return h(Modal, [h(childComponent)]);
    },
  };
}

// Routes
{
  path: '/customers/:clientId',
  component: customerView,
  meta: {
    auth: true,
  },
  children: [
    {
      path: 'addAddress',
      component: wrapInsideModal(dataViewAdd),
    },
  ],
},
like image 167
Decade Moon Avatar answered Sep 22 '25 12:09

Decade Moon