portal-vue icon indicating copy to clipboard operation
portal-vue copied to clipboard

Portal changes scopeId for some elements

Open danieltamas opened this issue 4 years ago • 4 comments

Portal version: 2.1.7 Nuxt version: 2.14.6

When portaling, for some reason the process changes the scopeId for some of the teleported elements.

Expected result:

<div data-v-1a9bb128="" id="header-content">
  <div data-v-1a9bb128="" id="left">
     <a data-v-1a9bb128="" href="/" class="logo-icon nuxt-link-active"></a>
  </div>
  <div data-v-1a9bb128="" id="right">
     <button data-v-1a9bb128="" id="friends" class="button-header"></button> 
     <button data-v-1a9bb128="" id="settings" class="button-header"></button> 
     <button data-v-1a9bb128="" id="logout" class="button-header"></button>
  </div>
</div>

Instead I'm getting this:

<div data-v-1a9bb128="" id="header-content">
   <div data-v-1a9bb128="" id="left">
      <a data-v-1a9bb128="" href="/" class="logo-icon nuxt-link-active"></a>
  </div>
  <div data-v-1a9bb128="" id="right">
     <button data-v-1a9bb128="" id="friends" class="button-header"></button> 
     <button data-v-56a57272="" id="settings" class="button-header"></button> 
     <button data-v-56a57272="" id="logout" class="button-header"></button>
  ></div>
</div>

The last 2 buttons in the #right div are getting a different scopeId for some reason: data-v-56a57272

What is the cause of this and what's the fix? If I leave a single element in the #right div, there's no problem. The moment I start adding, I get this.

Thanks

danieltamas avatar Nov 12 '20 15:11 danieltamas

I'm not sure how to read this code sample - is all of this portal-content?

I'd apprechiate actually runnable code so I can replicate what you experience

LinusBorg avatar Nov 12 '20 16:11 LinusBorg

Fair enough. Thanks for pointing that out.

Header.vue
<template>
   <div>
    ....
   <portal-target name="header" slim>
      <div id="header-content">
         <div id="left">
            <a href="/" class="logo-icon nuxt-link-active"></a>
         </div>
         <div id="center"></div>
         <div id="right"></div>
      </div>
   </portal>
   </div>
</template>

<style lang="less" scoped> ... </style>
Account.vue
<template>
    <div>
    ....
    <portal to="header">
       <div id="header-content">
         <div id="left">
            <a href="/" class="logo-icon nuxt-link-active"></a>
         </div>
         <div id="right">
            <button id="friends" class="button-header"></button> 
            <button id="settings" class="button-header"></button> 
            <button id="logout" class="button-header"></button> 
         </div>
      </div>
    </portal>
    </div>
</template>

<style lang="less" scoped> ... </style>

These 2 produce the initial result.

Later edit: I also tried using MountingPortal but the rendered HTML does not take into account the classes nor the ID I set so had to use this version. Used it with and without scoped-slot.

danieltamas avatar Nov 12 '20 17:11 danieltamas

I see. The issue is likely that the divs from the target's default slot are re-used when the portal's content is rendered.

You should put a key on the target's default slot root nodes to make sure they are properly replaced.

However I'm not sure that the result is what you want: the portal's content shown in the target will have the scope id's of the portal, not the target - as it's the portal's content.

LinusBorg avatar Nov 12 '20 19:11 LinusBorg

Yup, you are correct. Is there a way to use the source's scopeId? Now everything is using the target scopeId

danieltamas avatar Nov 12 '20 19:11 danieltamas