Skip to main content

Wraplet

What is a Wraplet?

A Wraplet is the central concept of this framework – it's an object that wraps a DOM node and gives it a structured identity: a clear responsibility, an explicit lifecycle, and a small public API.

You can think of a wraplet as a typed, lifecycle-aware bridge between a real element in the document and the JavaScript/TypeScript logic that drives it.

What makes an object a Wraplet?

Technically, anything that implements the Wraplet interface is a wraplet. The interface is intentionally minimal and consists of just two properties:

  • [WrapletSymbol] – a marker property set to true, used to reliably distinguish wraplets from plain objects,
  • wraplet – an object implementing the WrapletApi interface, which exposes the wraplet's lifecycle.

The WrapletApi is what allows wraplets to be composed: because every wraplet exposes the same lifecycle contract (initialize, destroy, status, addDestroyListener), parent wraplets can manage their children uniformly, regardless of what those children actually do internally.

In other words: a wraplet is not defined by extending a particular class or by being attached to a node in a particular way. It's defined by the contract it implements. Anything that fulfills the Wraplet interface participates in the wraplet ecosystem.

You can find the technical reference of the interface HERE.

What a Wraplet represents

A wraplet typically represents one meaningful unit of behavior connected to a DOM node, for example:

  • a button,
  • an input field,
  • a form,
  • a tabs widget,
  • a wrapper around a third-party component,
  • a coordinator for a group of smaller wraplets.

The DOM node is the place where the wraplet "lives", but the node alone is not the reason the wraplet exists. The reason is the responsibility the wraplet encapsulates around that node.

For more on how to think about modeling your interface in terms of wraplets, see How to think in Wraplet.

Why does this contract matter?

Because every wraplet shares the same minimal API, the framework can offer a number of guarantees:

  • Composability – any wraplet can become a dependency of another wraplet, and the parent can manage its children's lifecycle without knowing their internal details.
  • Predictable lifecycle – every wraplet can be initialized and destroyed in a consistent, asynchronous way. See Lifecycle for details.
  • Safe cleanup – resources owned by a wraplet (event listeners, timers, child wraplets, external widgets) can be released deterministically when the wraplet is destroyed.
  • Encapsulation – a wraplet exposes a small, meaningful public API instead of leaking its internal DOM structure to the outside world.

How do you create a Wraplet?

You have two options:

  1. Implement the Wraplet interface manually. This gives you full control and is sometimes useful for very specialized cases or for adapting external objects to the wraplet ecosystem.
  2. Extend one of the abstract base classes provided by the framework:

In most real-world code you'll extend one of the abstract classes, because they remove a lot of boilerplate and wire useful features (like the NodeManager and lifecycle hooks) for you automatically.

Wraplet vs the DOM node

It's important to keep two things separate in your mind:

  • The DOM node is part of the document. It's owned by the browser and may be created or removed at any time.
  • The wraplet is a JavaScript/TypeScript object that wraps that node, gives it behavior, and manages the resources tied to it.

A wraplet can be destroyed independently of its node (cleaning up listeners and child wraplets), and a node may exist without ever being wrapped. The framework's job is to keep the relationship between the two well-defined and predictable.

Reference