Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested routes from Vue Router break when used inside PortalVue #289

Open
boardend opened this issue Mar 4, 2020 · 8 comments
Open

Nested routes from Vue Router break when used inside PortalVue #289

boardend opened this issue Mar 4, 2020 · 8 comments

Comments

@boardend
Copy link
Contributor

boardend commented Mar 4, 2020

Version

2.1.7

Reproduction link

https://codesandbox.io/s/great-elgamal-y285j

  • The problem can be toggled with the checkbox inside the footer.
  • See router.js, MainView.vue and ModalOutlet.vue.

Steps to reproduce

Use <router-view /> with nested routes inside a <portal> to render the nested routes somewhere else in the app (e.g. a lightbox modal that is logically a child of some other component/route, but should be rendered somewhere close to the root component).

What is expected?

The route matching will work the same, no matter if the <router-view /> is inside a <portal> or not.

What is actually happening?

When inside a <portal>, the nested route gets replaced with the parent route from where the <portal> was used.

@tmorehouse
Copy link

This would be because the child <router-view> is no longer nested within the parent <router-view> when portalled: the parent hierarchy changes (https://portal-vue.linusb.org/guide/caveats.html#known-caveats) if your <portal-target> is not rendered within your parent <router-view> container.

@tmorehouse
Copy link

One workaround would be to use named <router-view>s, and set the "child" route to be targeted to that name view (https://router.vuejs.org/guide/essentials/named-views.html#named-views)

@boardend
Copy link
Contributor Author

boardend commented Mar 4, 2020

@tmorehouse thanks for your quick reply!

I've just tried out your proposed workaround and it seems that nested views cannot use named views from "upstream" routes/components. It only works when the named <router-view> is defined inside the parent component.

@tmorehouse
Copy link

tmorehouse commented Mar 4, 2020

There is a way to force a particular parent on a component... it requires manual mounting though (note I haven't tested this example code, but I have done similar for other things):

<template>
  <div>
    <router-view ref="parentView" />
    <div ref="portalTarget" />
  </div>
</template>

<script>
import { PortalTarget } from 'portal-vue'

export default {
  mounted() {
    const parentComponent = this.$refs.parentView
    const childElement = this.$refs.portalTarget
    const pt = new PortalTarget({
      el: childElement,
      parent: parentComponent,
      propsData: {
        name: 'modal-portal'
      }
    })
    // Ensure the portal target is destroyed
    this.$once('hook:beforeDestroy', () => pt.$destroy())
  }
}
</script>

EDIT:

This will probably not work since <router-view> is a functional component (which doesn't have a Vue this instance).

You would need to render the portal target inside of the parent router-view, and pass the top route's parent instance to the parent of the dynamically added portal-target. Or one could manually mount the child router-view and pass an explicit parent to it.

@boardend
Copy link
Contributor Author

boardend commented Mar 9, 2020

As you already stated, I couldn’t get the functional router-view component mounted with a manually set parent component. And when I tried mounting it with a wrapper component (as proposed here https://stackoverflow.com/questions/54239343/how-do-you-unit-test-a-vue-js-functional-component-with-a-render-function-that-r/54277077#54277077) Vue Router didn’t pick up the router-view element.

I’m currently perusing a solution without Portal-Vue which works, but is not as nice if I were able to send the route component to the desired location.

If there isn’t a nice/easy solution to get Vue Router and Portal-Vue working together, we should use this issue to add some notes to the Portal-Vue Known Caveats.

@LinusBorg
Copy link
Owner

This is indeed a caveat, which is a consequence of the $parentcaveat.

<router-view> internally walks the $parent chain to find out how many (if any) parent <router-view> components there are.

We should indeed add a note to the docs.

Also note that this is not a problem in vue-simple-portal, and will also not be an issue with Vue 3's native <teleport> component.

@boardend
Copy link
Contributor Author

I've switchd to vue-simple-protal which indeed fixes this problem. Added a small note to the docs anyway, see #307

@LinusBorg
Copy link
Owner

LinusBorg commented Jul 24, 2020

Thanks! Will close then docs change has been deployed.

LinusBorg added a commit that referenced this issue Dec 22, 2020
* fix(docs): fix 'weither' typo (#282)

* build(deps): bump websocket-extensions from 0.1.3 to 0.1.4 (#304)

Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](faye/websocket-extensions-node@0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump lodash from 4.17.15 to 4.17.19 (#306)

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](lodash/lodash@4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add nested routes caveats to docs (#289) (#307)

* fix(docs): fix 'aleways' typo (#316)

* Update caveats.md (#312)

Co-authored-by: Wutichai Chansawat <synycboom@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Schmuki <boardend@users.noreply.github.com>
Co-authored-by: Leonidas Arvanitis <l.arvanitis@kinisys.com>
Co-authored-by: Christopher Vrooman <cdvrooman@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants