mountToElement function

BloomMountHandle mountToElement(
  1. BloomNode node,
  2. Element root, {
  3. @internal bool trackHotReloadMount = true,
})

Mounts a BloomNode descriptor tree directly into the provided DOM root element.

Instantiates real DOM elements, sets up event handlers, and establishes reactive signal subscriptions managed by an internal cleanup scope (_Region). Appends the resulting DOM nodes to root.

Returns a BloomMountHandle holding cleanup disposers. If mounting fails with an uncaught exception and bloomDevErrorOverlayEnabled is active, renders an in-browser error overlay into root.

final container = web.document.getElementById('my-widget')!;
final handle = mountToElement(
  Button(
    text: 'Click Me',
    on: {'click': (e) => print('Clicked')},
  ),
  container,
);

Implementation

BloomMountHandle mountToElement(
  BloomNode node,
  web.Element root, {
  @internal bool trackHotReloadMount = true,
}) {
  final active = _activeDevMountHandle;
  if (trackHotReloadMount &&
      _isHotReloadTrackingActive() &&
      active != null &&
      !active.isDisposed &&
      identical(active._root, root)) {
    if (active._tryHotReplace(node)) return active;
    active.dispose();
  }

  if (trackHotReloadMount &&
      _isHotReloadTrackingActive() &&
      _tryHotReplaceAcrossModule(node, root)) {
    // DDC re-executes the entry module, so the active handle may belong to the
    // previous module instance. Keep its global disposal hook as the owner.
    return BloomMountHandle(root, [
      () {
        try {
          _callDisposeActiveMount();
        } catch (_) {}
      },
    ]);
  }

  final region = _Region();
  try {
    final domNodes = _mountNode(node, region);
    for (final n in domNodes) {
      root.appendChild(n);
    }
    final handle = BloomMountHandle._(
      root,
      region.disposers.toList(),
      region: region,
      descriptor: node,
      rootNodes: domNodes,
    );
    if (trackHotReloadMount && _isHotReloadTrackingActive()) {
      _activeDevMountHandle = handle;
      _installHotReloadHooks();
    }
    return handle;
  } catch (error, stackTrace) {
    region.disposeAll();
    BloomJsDevTools.notify('mount-error', {
      'error': error.toString(),
      'stackTrace': stackTrace.toString(),
    });
    if (bloomDevErrorOverlayEnabled || _isHotReloadTrackingActive()) {
      root.textContent = '';
      final overlayHost = web.document.createElement('div');
      overlayHost.innerHTML = renderDevErrorOverlay(error, stackTrace).toJS;
      root.appendChild(overlayHost);
      final handle = BloomMountHandle(root, []);
      if (trackHotReloadMount && _isHotReloadTrackingActive()) {
        _activeDevMountHandle = handle;
        _installHotReloadHooks();
      }
      return handle;
    }
    rethrow;
  }
}