LinusBorg / portal-vue

A feature-rich Portal Plugin for Vue 3, for rendering DOM outside of a component, anywhere in your app or the entire document. (Vue 2 version: v2.portal-vue.linusb.org)
http://portal-vue.linusb.org
MIT License
3.89k stars 186 forks source link

$store is undefined when using <MountingPortal> #199

Closed bgondy closed 5 years ago

bgondy commented 5 years ago

When I use <MountingPortal> to render a component outside of the main Vue component, Vuex is not available.

<!-- public/index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- ... -->
  </head>
  <body>
    <div id="app"></div>
    <div id="test"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
<template>
  <div id="app">
    <MountingPortal name="test-component" mountTo="#test">
      <TestComponent/>
    </MountingPortal>
  </div>
</template>

<script>
import TestComponent from "./components/TestComponent";

export default {
  name: 'app',
  components: {
    TestComponent,
  }
}
</script>
<!-- TestComponent.vue -->
<template>
    <div>
        <h1>Hello world</h1>
    </div>
</template>

<script>
    export default {
        name: 'TestComponent',
        mounted() {
            console.log(this);
        },
    };
</script>

The component is rendered but this.$store is not defined.

If I use <Portal> and <PortalTarget>, this.$store exists.

<!-- App.vue -->
<template>
  <div id="app">
    <Portal to="my-portal" append>
      <TestComponent/>
    </Portal>

    <PortalTarget name="my-portal"></PortalTarget>
  </div>
</template>

<script>
import TestComponent from "./components/TestComponent";

export default {
  name: 'app',
  components: {
    TestComponent,
  }
}
</script>

With portal-vue@1 and targetEl, I have access to the store (but with other known issues though).

Is it the expected behavior with the new <MountingPortal> component or am I missing something ?

Please note I've encountered a similar issue with vue-i18n (See https://github.com/kazupon/vue-i18n/issues/184#issuecomment-483166528).

LinusBorg commented 5 years ago

I'll rate this a bug and look into it, thanks for reporting.

Edit: Found the iussue:

https://github.com/LinusBorg/portal-vue/blob/develop/src/components/mounting-portal.tsx#L107

Now the question is, WTH did comment that out?

Will fix it and add a test for it.

tmorehouse commented 5 years ago

Would you want the generated Portal-Target parent to be the Portal creating it (parent = this), or the parent of the Portal? i.e. parent = this.$parent

LinusBorg commented 5 years ago

In the context of this issue, both should work.

However I would tend to the second as that would mean that the number of steps to reach the portal's parent is the same as with a normal portal.

But I have to double check

tmorehouse commented 5 years ago

Or could do the following:

parent = this.$parent || this
LeBenLeBen commented 5 years ago

@bgondy Did that fixed your issue?

I'm using 2.1.5 and having the issue with Vue-i18n throwing i18n is undefined every time $t is called.

I'm using it through morkro/vue-a11y-dialog which is using <mounting-portal append :mount-to="portalTarget"></mouting-portal>.

Once I move my child component outside of the Portal, everything works fine.

bgondy commented 5 years ago

@LeBenLeBen Yes it fixed the issue with VueX.

On the other hand, I faced the exact same issue with i18n on a previous project and I have had to roll back to v1 to get it working (time was running out…). But I think this is more related to how Vue-i18n works than portal-vue.

Please take a look at my comment here : https://github.com/kazupon/vue-i18n/issues/184#issuecomment-483166528

Hope it helps.