Normally, when we create components in Vue they naturally appear within the DOM structure where we'd expect them to be. However, sometimes this doesn't make sense. A good example of this is a modal - normally, a modal should appear on top of everything on the page - so if we create it within a component where it logically makes sense, it may appear behind certain HTML elements or require some weird CSS styling to get it to the top.
Fortunately, there is an easy way to solve for this problem in Vue, called <Teleport>
. The <Teleport>
tag lets us define something within a component, and then "teleport" it anywhere we want in the code. Let's look at how it works.
How Teleport works in Vue
Suppose we have a simple component in Vue called Modal.vue
which contains a modal. It looks a little like this:
<script>
export default {
data() {
return {
display: false
}
}
}
</script>
<template>
<button id="show-modal" @click="display == true ? display = false : display = true">Show Modal</button>
<div class="modal" v-if="display">
My Modal
</div>
</template>
In our structure, this modal sits quite deep in our application structure:
Since Modal.vue
is so deep in our structure, it may not appear on top of the rest of our content as we want. As such, we'd ideally want it to be a direct child of the body
tag. Using <Teleport>
, We can adjust our component to "teleport" it to be a direct child of the body
tag like so:
<script>
export default {
data() {
return {
display: false
}
}
}
</script>
<template>
<button id="show-modal" @click="display == true ? display = false : display = true">Show Modal</button>
<Teleport to="body">
<div class="modal" v-if="display">
My Modal
</div>
</Teleport>
</template>
The to
attribute of Teleport
is expected to be a valid CSS selector. Now our .modal
div will be teleported to be a direct child of the body, so it will always appear on top, rather than being deeply nested within our Vue structure.
Disabling a Teleport tag
We can disable a Teleport
tag based on certain logic using the :disabled
attribute. For example, we could check for the value of myToggle
being set to true, by using the following code:
<Teleport :disabled="myToggle"></Teleport>
Above, if myToggle
is set to true
, the Teleport
simply won't work, meaning we can only enable it when we want to. As such, Teleport
is a very useful tag in Vue for adjusting where and when we see certain content. It's also OK to use multiple Teleport
tags within the same Vue template.