Skip to content

View API (vanilla)

The vanilla API for building custom collaborative elements. For usage with side-by-side examples, see Custom elements; for the React equivalent, see the React API.

import { playhtml, html, svg, repeat, classMap, styleMap, nothing } from "playhtml";

Binds an initializer to one element by id and returns a handle. Callable before or after playhtml.init() and before or after the element exists in the DOM — binding happens once both are present (like customElements.define).

const handle = playhtml.register("my-counter", init);
  • The element needs a stable, unique id (it is the elementId). The can-play attribute is optional — register implies it.
  • Re-registering the same id replaces its initializer.

Registers a reusable capability under an attribute name. Every element carrying [capabilityName] binds — including ones added later, or rendered by a view. The imperative counterpart of init({ extraCapabilities }).

playhtml.define("can-note", init);

Defining a name that collides with a built-in capability throws. Each bound element still needs a unique id.

playhtml.getHandle(elementId, capability?)

Section titled “playhtml.getHandle(elementId, capability?)”

Returns a handle for any bound element. Because data is keyed by capability and id, pass the capability name when one element carries more than one.

const handle = playhtml.getHandle("card-1", "can-move");

The full annotated property list is on Element API. The view argument is ctx — see Callback context.

defaultData must be an object (or a function that returns one), not a bare value like 0 or "". Use { count: 0 }, not 0.

A valid initializer provides exactly one update path — view or updateElement.

view receives ctx (Callback context). Drive ctx.setData from @click handlers, not during render.

onMount gets getters (getData(), getElement(), …) instead of live values. See Element API → onMount for the playhtml.ready pattern.

Returned by register and getHandle. Reads and writes resolve the live handler lazily — a handle obtained before binding works once the element exists.

{
  id,
  getElement(),      // null until bound
  getData(),         // undefined until bound
  setData(next),
  setLocalData(next),
  setMyAwareness(next),
  requestUpdate(),   // no-op without a view
  unregister(),      // detach + run onMount cleanup; shared data is kept
}

A write through a handle whose element hasn’t bound yet is dropped (with a dev-mode warning); reads return undefined.

playhtml re-exports the lit-html pieces a view needs. unsafeHTML is intentionally not exported, so interpolated values stay auto-escaped.

ExportUse
htmlthe tagged template for view output
svgSVG fragments (e.g. <path> inside <svg>)
repeat(items, keyFn, template)keyed lists — key by a stable unique id
classMap(obj)conditional classes
styleMap(obj)conditional inline styles (safer than a style string)
nothingrender nothing (or just return null / undefined)

See the lit-html templating guide for the full template syntax.