hydrateElement function

BloomMountHandle hydrateElement(
  1. BloomNode root,
  2. Element element
)

Hydrates a server-rendered DOM tree inside element with event listeners in place.

Walks the existing DOM children in lockstep with the root descriptor tree, attaching event listeners and syncing attributes without destroying and recreating existing DOM nodes.

Hydration Eligibility

True in-place hydration is performed when root consists exclusively of static nodes:

Mismatch Handling & Fallback

A hydration mismatch occurs when:

  1. The descriptor tree contains any non-static/reactive node.
  2. A DOM node's tag name does not match the descriptor's tag (e.g. <p> vs <div>).
  3. A DOM node type differs from the expected descriptor (e.g. Element vs Text node).
  4. Child counts differ between the descriptor tree and the actual DOM.

When a mismatch occurs, hydrateElement performs no destructive partial updates. Instead, it safely clears element (element.textContent = '') and falls back to a clean full mount via mountToElement.

final container = web.document.getElementById('content')!;
final handle = hydrateElement(
  Div(
    className: 'container',
    children: [
      const H1(text: 'Welcome'),
      Button(
        text: 'Submit',
        on: {'click': (e) => submitForm()},
      ),
    ],
  ),
  container,
);

Implementation

BloomMountHandle hydrateElement(BloomNode root, web.Element element) {
  if (_isStaticallyHydratable(root)) {
    final disposers = <void Function()>[];
    if (_hydrateStatic(root, element, disposers)) {
      return BloomMountHandle(element, disposers);
    }
    // Structural mismatch — the walk above only reads/patches attributes
    // and text content in place; it never removes or reorders DOM, so
    // falling through to the full remount below is always safe.
  }
  if (element.childNodes.length > 0) {
    element.textContent = '';
  }
  return mountToElement(root, element);
}