Subscribe on changes!
avatar
May 5th 2022

What problem does this feature solve?

One of the main features of Vue is to control, what components are displayed. Teleport however requires that an element is mounted before the teleport tag is mounted. If for some reason the teleport target is removed but mounted again, the teleport does not work.

What I want is: If teleport is enabled (:disable="false"), then look for the element to be teleported to. return error or warning if not found. teleport if found.

This feature would make teleport a lot more easy to use, because it fits better into an Vue environment where everything is reactive.

As for a use-case: I currently want to teleport an input-field to a sidebar (https://www.primefaces.org/primevue/sidebar) that is displayed on small displays. The sidebar is displayed when I click on the inputfield. Even if I make sure that the teleport is enabled after (up to 10sec) the sidebar is displayed, the teleport fails silently.

What does the proposed API look like?

If teleport is enabled (:disable="false"), then look for the element to be teleported to. return error or warning if not found. teleport if found.

avatar
May 5th 2022

You should be able to use a key to force the recreation of the teleport

avatar
May 5th 2022

It has a wierd workaround, that I found seconds before giving up:

    <Sidebar v-model:visible="showMobile" position="top">
      <div id="mobileTarget"></div>
    </Sidebar>
    <teleport
      v-if="ready"
      to="#mobileTarget"
      :disabled="disableTeleport"
    >
    ....
    @focus="switchToMobile"
    ....
</teleport>
 data() {
    return {
      showMobile: true,            //Initially the teleporttarget is present 
      ready: false,                     // Initially teleport is not created. 
      disableTeleport: true,       
    };
  },
mounted() {
    this.ready = true;                 //Delays the mount, therefore teleport will not throw an error, because teleporttarget is still present
    this.showMobile = false;     //removes teleporttarget, so its not displayed
  },
methods:{
allowTeleportToMobile(): boolean {
      return this.breakpoint === "xs" || this.breakpoint === "sm";
      },
 switchToMobile() {
      if (this.allowTeleportToMobile && !this.showMobile) {
        this.showMobile = true;              // first make the teleporttarget available 
        this.ready = false;                       // remove the teleport  
        setTimeout(() => {                      //wait a little (it doesn't work without setTimeout
          this.disableTeleport = false;     //enable the teleport 
          this.ready = true;                     // render it ==> now it teleports properly.
        }, 1);
      }
    },
}

But its a very verbose and ugly workaround if you ask me. The teleport should check for the existence of the target, when activated. I would even propose that the target can be a vue component it self, but it would certainly help if that mounted requirement is gone.

Don't know what exactly you were proposing with the key. I only know it from lists (v-for), which isn't my current use-case.

avatar
May 15th 2022

@telion2 the work around with key would be adding the :key attribute to the component (or teleport, not sure exactly which is most appropriate @posva). If you change the key, Vue will register that when diffing and that will force a re-render

Its not a feature that has to be exclusively used with v-for or iteration over data. It can be used in any situation.

avatar
Nov 7th 2022

Have a very similar usecase — using portal-vue to make it work — but would be nice if Teleport supported these scenarios.