unbind

Stop a node’s bindings and descendant listeners while retaining the DOM.

unbindCleanup and Unbind

Stop a node’s bindings and descendant listeners while retaining the DOM.

Overview

The unbind function in Regor is responsible for removing bound data and associated logic from a DOM node and its descendants. This function is crucial for cleaning up data bindings and event listeners when elements are removed from the DOM or when they are no longer needed.

Try it live

Own a node through its full lifetimeLive API

Source value: 0 · Node: absent

0Source observers
0Root unbinders
0Custom cleanup calls

Unbind keeps the node but freezes its bindings. Remove + drain removes it and flushes deferred cleanup.

import {
  addUnbinder,
  createApp,
  drainUnbind,
  getBindData,
  html,
  observerCount,
  onUnmounted,
  ref,
  removeNode,
  sref,
  unbind,
  useScope,
} from 'regor'

export function createCleanup(interactive = false) {
  const host = sref<HTMLElement | null>(null)
  const source = ref(0),
    value = ref(0),
    present = ref(false),
    bound = ref(false)
  const observers = ref(0),
    callbacks = ref(0),
    registered = ref(0)
  let node: HTMLElement | null = null
  const inspect = () => {
    observers(observerCount(source))
    registered(node ? getBindData(node).unbinders.length : 0)
  }
  const mount = () => {
    if (!host() || node) return
    node = document.createElement('div')
    node.className = 'directive-card api-owned-node'
    host()!.appendChild(node)
    createApp(
      useScope(() => ({ source })),
      {
        element: node,
        template:
          '<strong>Owned node</strong><p>Bound value: <output r-text="source"></output></p>',
      },
    )
    addUnbinder(node, () => callbacks(callbacks() + 1))
    present(true)
    bound(true)
    inspect()
  }
  const detach = () => {
    if (node) unbind(node)
    bound(false)
    inspect()
  }
  const remove = async () => {
    if (!node) return
    removeNode(node)
    await drainUnbind()
    node = null
    present(false)
    bound(false)
    inspect()
  }
  onUnmounted(() => {
    if (node) {
      unbind(node)
      node.remove()
    }
  })
  return {
    interactive,
    host,
    value,
    present,
    bound,
    observers,
    callbacks,
    registered,
    mount,
    detach,
    remove,
    increment: () => {
      source(source() + 1)
      value(source())
      inspect()
    },
  }
}

export const cleanupTemplate = html` <div class="guide-demo">
  <div class="guide-session-bar">
    <button type="button" @click="mount" :disabled="!interactive || present">
      Mount node</button
    ><button type="button" @click="increment" :disabled="!interactive">
      Write +1</button
    ><button type="button" @click="detach" :disabled="!interactive || !bound">
      Unbind</button
    ><button type="button" @click="remove" :disabled="!interactive || !present">
      Remove + drain
    </button>
  </div>
  <p>
    Source value: <strong>{{ value }}</strong> · Node: {{ present ? 'present' :
    'absent' }}
  </p>
  <div :ref="host"></div>
  <div class="guide-metrics">
    <div><output>{{ observers }}</output><span>Source observers</span></div>
    <div><output>{{ registered }}</output><span>Root unbinders</span></div>
    <div><output>{{ callbacks }}</output><span>Custom cleanup calls</span></div>
  </div>
  <p class="guide-hint">
    Unbind keeps the node but freezes its bindings. Remove + drain removes it
    and flushes deferred cleanup.
  </p>
</div>`
import { createApp, RegorConfig, useScope } from 'regor'
import { apiExamples } from './examples'

const element = document.getElementById('api-demo')
const name = element?.dataset.example
if (element && name && Object.hasOwn(apiExamples, name)) {
  const example = apiExamples[name as keyof typeof apiExamples]
  const scope = useScope<object>(() => example.create(true))
  const config =
    'config' in scope.context && scope.context.config instanceof RegorConfig
      ? scope.context.config
      : undefined
  createApp(scope, { element, template: example.template }, config)
}

Mount, write, unbind, or remove and drain. Watch the DOM, observer count, and registered cleanup.

Usage

Removing Bound Data and Logic

The unbind function takes a single parameter:

  • node: The DOM node from which you want to start the unbinding process. The function will recursively unbind data and logic from this node and its descendants.

Example

import { unbind } from 'regor'

// Remove bound data and associated logic from a DOM node and its descendants
const someElement = document.getElementById('example')
unbind(someElement)

Parameters

  • node: The DOM node from which you want to start the unbinding process. The function will recursively unbind data and logic from this node and its descendants.
Unbind leaves the rendered nodes in place

The retained node can show its last value while the source continues to change. Remove it separately when its DOM is no longer needed.

Notes

  • The unbind function is typically used internally within Regor to clean up data bindings and event listeners associated with DOM nodes that are being removed or are no longer needed.

  • When called on a specific DOM node, the function recursively traverses all child nodes, unbinding data and logic as it goes.

  • The primary purpose of this function is to ensure that there are no memory leaks or lingering event listeners when elements are removed from the DOM.

  • It is essential to call the unbind function when elements are removed from the DOM manually or as part of a Regor component's lifecycle management.

  • In most cases, you do not need to call this function explicitly, as Regor handles the unbinding process automatically when components are unmounted or when elements are removed from the DOM through Regor's rendering and cleanup mechanisms.

See Also

Related APIs and guides Continue with the references connected to unbind.

Back to the API list