We use cookies to enhance your experience on the site
CodeWorlds

Teleport

In NOVA LAB the alarm system displays an alert on the station's main screen, regardless of which module triggered it. Vue has

<Teleport>
- a mechanism for rendering content in a different place in the DOM, outside the component hierarchy.

The Problem

Modals, toasts, and popups logically belong to a component, but visually they should be rendered at the top level of the DOM (e.g., directly in

<body>
) to avoid issues with
z-index
,
overflow: hidden
, and positioning.

Teleport Basics

1<script setup>
2import { ref } from 'vue'
3const showModal = ref(false)
4</script>
5
6<template>
7  <div class="module-panel">
8    <h2>Oxygen Module</h2>
9    <button @click="showModal = true">Show Alert</button>
10
11    <Teleport to="body">
12      <div v-if="showModal" class="modal-overlay">
13        <div class="modal">
14          <h3>Critical Alert!</h3>
15          <p>Oxygen level below 20%</p>
16          <button @click="showModal = false">Dismiss</button>
17        </div>
18      </div>
19    </Teleport>
20  </div>
21</template>

The content inside

<Teleport>
is physically rendered in
<body>
, but logically belongs to the component - it has access to its data and props.

The to Attribute

The

to
attribute accepts a CSS selector:

1<!-- To body -->
2<Teleport to="body">...</Teleport>
3
4<!-- To an element with an ID -->
5<Teleport to="#modal-container">...</Teleport>
6
7<!-- To an element with a class -->
8<Teleport to=".notifications">...</Teleport>

Disabled Teleport

You can dynamically disable teleportation:

1<script setup>
2import { ref } from 'vue'
3const isMobile = ref(false)
4</script>
5
6<template>
7  <!-- On mobile render locally, on desktop in body -->
8  <Teleport to="body" :disabled="isMobile">
9    <div class="popup">
10      <p>Popup content</p>
11    </div>
12  </Teleport>
13</template>

When

disabled=true
, the content renders in its original place in the component tree.

Multiple Teleports to the Same Target

You can have multiple

<Teleport>
elements rendering to the same element - content is appended in order:

1<template>
2  <Teleport to="#notifications">
3    <div class="toast">Alert 1</div>
4  </Teleport>
5
6  <Teleport to="#notifications">
7    <div class="toast">Alert 2</div>
8  </Teleport>
9</template>
Go to CodeWorlds