Dynamic Tags

Use a runtime value as the tag name of an element inside an html template.


Description

Inside any html template you can interpolate the tag name itself, opening the door to elements whose type is decided at render time. The value can be:

  • a string (a built-in HTML tag like 'section', or a registered Web-Component name like 'my-card');
  • a Wompo component (the function returned by defineWompo) — Wompo picks up the component's registered tag name automatically;
  • the result of any JS expression that evaluates to one of the above.


Usage

import { defineWompo, html } from 'wompo';

export default function Heading({ level = 1, children }) {
  const tag = 'h' + Math.min(Math.max(level, 1), 6);
  return html`<${tag} class="heading">${children}</${tag}>`;
}

defineWompo(Heading);

The same syntax works for choosing a wrapper between, for example, a section and an article:

html`<${type === 'article' ? 'article' : 'section'} class=${s.box}>
  ${children}
</${type === 'article' ? 'article' : 'section'}>`;

You can also dynamically pick between two Wompo components in the same way:

import { defineWompo, html } from 'wompo';
import Card from './Card.js';
import Pill from './Pill.js';

export default function Item({ variant, ...props }) {
  const Component = variant === 'pill' ? Pill : Card;
  return html`<${Component} ...=${props} />`;
}

defineWompo(Item);

Rules and gotchas

Open and close must match. When a tag is dynamic, both the opening <${tag}> and the closing </${tag}> need to interpolate the same value. The renderer uses this to keep template caching consistent.

A few more rules to keep in mind:

  • Self-closing dynamic tags are supported ( <${Component}/>) and are expanded to a full open/close pair internally.
  • Changing the tag value across renders creates a new element instance: any state tied to the previous DOM node is reset.
  • You can combine dynamic tags with the attrs spread to build fully generic wrappers.