Context:
I have a Vue app rendered inside a shadow Dom. There I have quite a few use-cases where I need teleports (https://vuejs.org/guide/built-ins/teleport.html).
Note that a few use-cases are based on Primevue: https://www.primefaces.org/primevue/autocomplete But I can say that all of the use-cases use: https://github.com/primefaces/primevue/blob/master/src/components/portal/Portal.vue
Teleports require a valid CSS Selector:
The to target of expects a CSS selector string or an actual DOM node. Here, we are essentially telling Vue to "teleport this template fragment to the body tag".
Problem
However, with the exception of "self", it was not possible to find a CSS Selector that could drill into the shadow DOM.
I was able to teleport anywhere else but not into the shadow Dom.
Code & My Attempts:
<HTML>
...
<body>
...
<customComponent id="customElement">
# shadow-root(open)
<div id="mainElement"
...
<Dialog
v-model:visible="showDialog"
appendTo="mainElement"
>
...
<div id="teleportTarget"></div>
...
<teleport
to="#teleportTarget"
>
...
I also tried a solution from here: https://forum.vuejs.org/t/how-can-i-use-teleport-inside-a-custom-webelement/130423/2 But opposed to Vue, PrimeVue only accepts Strings. Even if using this solution I wasn't able to make it work.
async mounted() {
const shadow = document.querySelector("#customElement")?.shadowRoot;
await this.$nextTick(); //I tried with and without nextTick
this.teleportTarget = shadow?.firstElementChild;
console.log(this.teleportTarget); //==> null
},
Question
Is there a query selector, that can drill into the shadow Dom, that can be used for Vue Teleports.
It seems, that I run into a lifecycle Issue. The solution was basically to "delay" the rendering of the teleport element like this:
<Dialog
v-if="ready"
:appendTo="teleportTarget"
>
....
data() {
return {
teleportTarget: null,
ready: false,
};
},
mounted() {
this.teleportTarget = this.$el.parentNode.firstElementChild;
this.ready = true;
},
I found using this.$el to be the more "vue-ish" solution, but it also worked with document.