Now.js Framework Documentation

Now.js Framework Documentation

ElementManager

EN 09 Nov 2026 03:28

ElementManager

Overview

ElementManager is the custom element management system in Now.js Framework. Used for registering, creating, and enhancing form elements.

When to use:

  • Need to create custom form elements
  • Need to enhance existing elements
  • Need to manage element lifecycle
  • Need auto-enhance via attributes

Why use it:

  • ✅ Register custom element types
  • ✅ Auto-enhance via data-element
  • ✅ Instance management
  • ✅ Container-based cleanup
  • ✅ Weak reference tracking

Basic Usage

Register Element Type

ElementManager.registerElement('currency', {
  enhance(element, config) {
    // Transform into currency input
    element.addEventListener('input', (e) => {
      e.target.value = formatCurrency(e.target.value);
    });
    return element;
  },
  destroy(instance) {
    // Cleanup
  }
});

HTML Auto-Enhance

<!-- Auto-enhanced by ElementManager -->
<input type="text" data-element="currency" name="price">
<input type="text" data-element="phone" name="phone">
<input type="text" data-element="date" name="birthday">

JavaScript API

// Create element programmatically
const element = ElementManager.create('currency', {
  name: 'amount',
  value: 1000
});

// Enhance existing element
const input = document.querySelector('#price');
ElementManager.enhance(input, { type: 'currency' });

API Reference

ElementManager.registerElement(type, implementation)

Register element type

Parameter Type Description
type string Element type name
implementation object Implementation with enhance/destroy
ElementManager.registerElement('rating', {
  enhance(element, config) {
    // Add star rating UI
    return element;
  },
  destroy(instance) {
    // Cleanup
  }
});

ElementManager.create(type, config)

Create new element

Parameter Type Description
type string Registered element type
config object Configuration

Returns: HTMLElement

const dateInput = ElementManager.create('date', {
  name: 'startDate',
  min: '2024-01-01'
});

ElementManager.enhance(element, config)

Enhance existing element

Parameter Type Description
element HTMLElement Element to enhance
config object Configuration

Returns: Object - Instance

const instance = ElementManager.enhance(input, {
  type: 'tags'
});

ElementManager.getInstance(id)

Get instance by ID. When two elements on the page share an id, this returns the one
enhanced last; once that one is destroyed, the id finds the other again.

Returns: Object|undefined

ElementManager.getInstanceByElement(element)

Get instance from element. Never returns another element's instance, even when the two
share an id.

Returns: Object|null

ElementManager.scan(container)

Scan and enhance elements in container

Parameter Type Description
container HTMLElement Container (default: document)
// After loading new content
ElementManager.scan(document.getElementById('form-container'));

ElementManager.destroy(id)

Destroy instance

Parameter Type Description
id string Instance ID

ElementManager.destroyContainer(container)

Destroy all instances in container

// Before removing container
ElementManager.destroyContainer(modal);
modal.remove();

ElementManager.hasElement(type)

Check if type is registered

Returns: boolean

Built-in Element Types

Now.js has pre-registered element types:

Type Description
text Text input with masking
number Number input with formatting
date Date picker
select Enhanced select
multiselect Multi-select with tags
color Color picker
tags Tag input
password Password with strength
range Range slider
search Search with autocomplete

Real-World Examples

Custom Element Registration

// Register phone number element
ElementManager.registerElement('phone', {
  enhance(element, config) {
    element.type = 'tel';
    element.placeholder = '(___) ___-____';

    element.addEventListener('input', (e) => {
      let value = e.target.value.replace(/\D/g, '');
      if (value.length > 0) {
        value = '(' + value;
      }
      if (value.length > 4) {
        value = value.slice(0, 4) + ') ' + value.slice(4);
      }
      if (value.length > 10) {
        value = value.slice(0, 10) + '-' + value.slice(10, 14);
      }
      e.target.value = value;
    });

    return element;
  },

  destroy(instance) {
    // Remove listeners if needed
  }
});

Form with Auto-Enhanced Elements

<form id="contact-form">
  <input data-element="text" name="name" placeholder="Name">
  <input data-element="phone" name="phone" placeholder="Phone">
  <input data-element="email" name="email" placeholder="Email">
  <input data-element="date" name="date" placeholder="Preferred Date">
  <button type="submit">Submit</button>
</form>

<script>
// Elements are auto-enhanced on page load
// Or manually scan:
ElementManager.scan(document.getElementById('contact-form'));
</script>

Dynamic Form Fields

function addField(type, name) {
  const element = ElementManager.create(type, {
    name: name,
    id: `field-${name}`
  });

  document.getElementById('dynamic-fields').appendChild(element);
}

// Usage
addField('date', 'startDate');
addField('currency', 'budget');

Common Pitfalls

⚠️ 1. Register Before Use

// ❌ Using unregistered type
ElementManager.create('custom-type', {});

// ✅ Register first
ElementManager.registerElement('custom-type', {...});
ElementManager.create('custom-type', {});

⚠️ 2. Cleanup Before Removing

// ❌ Removing element directly
container.remove();

// ✅ Destroy first
ElementManager.destroyContainer(container);
container.remove();

⚠️ 3. Same Id in a Modal and the Page Under It

An element that shares an id with a live element elsewhere gets its own instance and
leaves the other one alone, and destroyContainer() tears down only what lies inside
the container. Ids are still looked up by the browser, though:
document.getElementById() returns whichever element comes first, so a script that
finds a field by id after the modal opened may reach the wrong one. Give modal fields
their own ids:

<!-- ❌ The page already has #customer_no -->
<input type="text" id="customer_no" name="customer_no">

<!-- ✅ -->
<label for="modal_customer_no">Customer code</label>
<input type="text" id="modal_customer_no" name="customer_no">