Hone logo
Hone
Problems

Vue Teleport Component: Dynamic Target Selection

This challenge focuses on implementing a reusable Vue component that utilizes the <teleport> feature to dynamically render content into a specified target element within the DOM. Teleport is incredibly useful for scenarios like modals, tooltips, or notifications that need to appear outside of the component's parent's DOM structure to avoid z-index or styling conflicts. Your task is to build a component that allows the user to specify the target element via a prop.

Problem Description

You need to create a Vue component called TeleportTarget that accepts a target prop. This prop will be a CSS selector string (e.g., '#modal-container', '.tooltip-wrapper'). The component should wrap its children and then use the <teleport> element to render those children into the DOM element matching the provided target selector.

Key Requirements:

  • target Prop: The component must accept a target prop, which is a string representing a CSS selector.
  • Dynamic Teleport Target: The <teleport> element within the component must dynamically use the value of the target prop as its to attribute.
  • Component Wrapper: The component should wrap its children within the <teleport> element.
  • Error Handling: If the target element specified by the target prop does not exist in the DOM when the component is mounted, the component should render its children directly within itself (without teleporting) and log an error to the console. This prevents the application from breaking.
  • Reactivity: If the target prop changes after the component is mounted, the teleport target should update dynamically.

Expected Behavior:

  1. When the component is mounted, it should attempt to find the element matching the target selector.
  2. If the element is found, the component's children should be teleported to that element.
  3. If the element is not found, the component's children should be rendered directly within the TeleportTarget component, and an error message should be logged to the console.
  4. If the target prop changes after mounting, the component should update the teleport target accordingly.

Edge Cases to Consider:

  • The target selector is invalid (e.g., contains syntax errors).
  • The target selector matches multiple elements. (The component should teleport to the first matching element.)
  • The target element is dynamically added to the DOM after the component is mounted.
  • The target element is removed from the DOM.

Examples

Example 1:

Input:
<TeleportTarget target="#modal-container">
  <div>This is the modal content.</div>
</TeleportTarget>

HTML (in the DOM):
<div id="modal-container"></div>

Output: The "This is the modal content." div is rendered inside the <div id="modal-container"> element. Explanation: The component finds the element with the ID "modal-container" and teleports the content inside it.

Example 2:

Input:
<TeleportTarget target=".tooltip-wrapper">
  <span>Tooltip text</span>
</TeleportTarget>

HTML (in the DOM):
<div class="container">
  <div class="tooltip-wrapper"></div>
</div>

Output: The "Tooltip text" span is rendered inside the <div class="tooltip-wrapper"> element. Explanation: The component finds the first element with the class "tooltip-wrapper" and teleports the content inside it.

Example 3: (Edge Case - Target Not Found)

Input:
<TeleportTarget target="#non-existent-element">
  <div>This content should stay here.</div>
</TeleportTarget>

HTML (in the DOM):
<div></div>

Output: The "This content should stay here." div is rendered directly within the <TeleportTarget> component. An error message is logged to the console indicating that the target element was not found. Explanation: The component fails to find the target element and renders its children directly within itself, logging an error.

Constraints

  • The component must be written in TypeScript.
  • The target prop must be a string.
  • The component should be reusable and not rely on any specific DOM structure outside of the target element.
  • The component should be performant; avoid unnecessary DOM manipulations.
  • The component should handle errors gracefully and not crash the application.

Notes

  • Consider using document.querySelector to find the target element.
  • Use Vue's reactivity system to ensure the teleport target updates when the target prop changes.
  • Think about how to handle the case where the target element is not found. Rendering the children directly within the component is a reasonable fallback.
  • Focus on creating a clean, well-documented, and reusable component.
  • Error logging should be done using console.error.
Loading editor...
typescript