Advanced Usage
Switching targets & sources
The to
prop of <portal>
and the name
prop of <portal-target>
can be changed dynamically with v-bind
, allowing you to send content of one <portal>
to a different <portal-target>
, or switch the source of a <portal-target>
from one <portal>
to another.
<portal v-bind:to="name">
Content will be dynamically sent to the destination that `name` evaluates to
</portal>
<portal-target v-bind:name="name">
by changing the 'name', you can define which portal's content should be shown.
</portal-target>
Scoped Slots
PortalVue can also be used with Scoped Slots! This allows you to send a scoped slot to a PortalTarget, which can then provide props for the slot content:
<portal to="destination" v-slot="{ message }">
<p>{{message}}</p>
</portal>
<portal-target
name="destination"
:slot-props="{message: 'Hello from the Target to You!'}"
/>
Result:
<!-- rendered in the target location-->
<p>Hello from the Target to You!</p>
Transitions
Portal Transitions
You can pass transitions to a <portal>
without problems. It will behave just the same when the content is being rendered in the <portal-target>
:
<portal to="destination">
<transition name="fade">
<p v-if="hasMessages" key="1">You have {{messages.length}} new messages</p>
<p v-else key="2">No unread messages</p>
</transition>
</portal>
However, if you use a <portal-target>
for multiple <portal>
s, you likely want to define the transition on the target end instead. This is also supported.
PortalTarget Transitions
<portal-target name="target">
<template v-slot:default="nodes">
<transition name="fade" mode="out-in">
<component :is="nodes[0]" />
</transition>
</template>
</portal-target>
Transitions for Targets underwent a redesign in PortalVue 3.0
. The new syntax is admittedly a bit more verbose and has a hack-ish feel to it, but it's a valid use of Vue's v-slot syntax and was necessary to get rid of some nasty edge cases with target Transitions that we had in PortalVue 2.*
.
Basically, you pass a transition to a slot named wrapper
and get an array called nodes
from its slot props.
You can the use Vue'S <component :is="">
to turn those into the content of the transition.
Here's a second example, using a <transition-group>
instead:
<portal-target name="target">
<template #default="nodes">
<transition-group name="fade">
<component :is="node" v-for="node in nodes" :key="node" />
</transition-group>
</template>
</portal-target>
Proper namespacing
In order to move content from Portals
to PortalTargets
, some intermediary state management is required to coordinate between the two. We call this the "wormhole".
In PortalVue <=2.*
, this wormhole was a singleton instance, and as a consequence, the namespace for to
and name
properties was also global.
In PortalVue 3.0
we still use a default wormhole, but now also support creating your own wormhole instance(s) and providing them to your portal components in different areas of your app - or different apps on the same page.
This makes working with names a bit less prone to conflicts, especially when 3rd-party libraries that you are using in your projects also use portal-vue to move things around without you even knowing.
So how does it work?
TODO: properly document using createWormhole()
Rendering outside of the Vue-App
TODO: Introduce createPortalTarget
and explain limited usage scenarios