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.9k stars 187 forks source link

Strange behavior and transitions not working #393

Closed sneakylenny closed 1 year ago

sneakylenny commented 1 year ago

Context (reproduction)

I have an Laravel Inertia application.

In the layout I have: The "fade" transition is included and works fine.

<PortalTarget name="title">
  <template #default="nodes">
    <transition name="fade" mode="out-in">
      <div v-if="nodes && nodes[0]">
        <component :is="nodes[0]" />
      </div>
    </transition>
  </template>
</PortalTarget>

In page dashboard I have:

<Portal to="title">Dashboard</Portal>

In page account I have:

<Portal to="title">Account</Portal>

In page test I have nothing, because A title can be missing and should not break the app.

The issue:

There is no animation when navigation though the pages:

portalvue-issue Example navigating from dashboard -> account -> test -> account -> dashboard

These alternative attempts yield the exact same result:

<PortalTarget name="title">
  <template #default="nodes">
    <transition name="fade" mode="out-in" duration="1000">
      <component :is="nodes[0]" v-if="nodes && nodes[0]" />
    </transition>
  </template>
</PortalTarget>

<!-- Even if I set the v-if to false it does not change anything -->

<PortalTarget name="title">
  <template #default="nodes">
    <transition name="fade" mode="out-in" duration="1000">
      <component :is="nodes[0]" v-if="false" />
    </transition>
  </template>
</PortalTarget>

Strange behavior

Then this code yielded especially weird results:

<PortalTarget name="title">
  <template #default="nodes">
    <transition name="fade" mode="out-in" duration="1000">
      <div v-if="false">
        <component :is="nodes[0]" />
      </div>
      <div v-else>TEST</div>
    </transition>
  </template>
</PortalTarget>

Which results in:

portalvue-issue2 Example navigating from dashboard -> account -> test -> account -> dashboard. Note that page "test" does not contain a portal component

Even though the v-if is hard-coded to false, it still shows somehow?

I could not make any sense of it and could not get the transition to work, I am now going for an alternative approach but felt the need to share this issue in case it can get fixed or if someone runs into the same issue.

ggedde commented 1 year ago

@timyourivh Any updates on this. I am running into the same issue. Trying to migrate from 2 to 3 and I can't get any transitions to work.

ggedde commented 1 year ago

I got it to work, but was different then what I was thinking. In v2 it worked without needing any transition state as it seemed to handle the transition itself. I think with v3 it tries to hand that off to vue. So transitions don't seem to work just because the portal contents have been updated. It seems to now require a transition state. Ideally, I would prefer not to need to do this.

Also the docs say <template v-slot:default="nodes">, but it only works for me if I use <template v-slot:wrapper="nodes">

So here is my work around wherever you are specifying the content:

<portal to="target">
   <div v-if="loaded">
   ...
   </div>
</portal>
...
const loaded = ref(false);
onMounted(() => {
   loaded.value = true;
});

and the target

<portal-target name="target">
   <template v-slot:wrapper="nodes">
      <transition name="fade">
         <component :is="nodes[0]" />
      </transition>
   </template>
</portal-target>
sneakylenny commented 1 year ago

@ggedde I decided to not use this package and fixed it by creating a "composable" like in nuxt 3.

I'm going to close this issue because I don't think it will be fixed anyway.