Skip to content

Sponsor

Sponsor

Additional Creation Patterns — Methods 5, 6, 7, 10, 12

This file covers the remaining five creation methods. These are lighter-weight approaches, each designed for a specific scenario. You may not use all of them every day, but understanding them rounds out your complete picture of the Dom Helpers element system.


Method 5: Manual Enhancement

What Is It?

Manual enhancement lets you take a plain element — one created by document.createElement() without auto-enhancement enabled — and explicitly give it the .update() method.

When to Use It

  • You have elements created before you enabled auto-enhancement
  • You are working with elements created by third-party code
  • You want fine-grained control over which elements get enhanced

Syntax

javascript
EnhancedUpdateUtility.enhanceElementWithUpdate(element);

How It Works

1️⃣  You pass an existing DOM element to the function
2️⃣  The function checks if the element already has .update()
    → If yes: returns the element unchanged (no double-enhancement)
    → If no: attaches .update() using Object.defineProperty
3️⃣  Returns the enhanced element

Examples

javascript
// Create a plain element (no auto-enhancement)
const div = document.createElement('div');

// Manually enhance it
EnhancedUpdateUtility.enhanceElementWithUpdate(div);

// Now .update() works
div.update({
  textContent: 'Enhanced manually!',
  style: { padding: '20px', background: '#f0f0f0' },
  classList: { add: ['my-div'] }
});

document.body.appendChild(div);

Enhancing Elements from Third-Party Code

javascript
// Some library creates an element for you
const datepicker = ThirdPartyLib.createDatepicker();

// Enhance it so you can use Dom Helpers' .update()
EnhancedUpdateUtility.enhanceElementWithUpdate(datepicker.element);

// Now use .update() to apply additional styling
datepicker.element.update({
  classList: { add: ['my-custom-datepicker'] },
  style: { border: '2px solid #007bff', borderRadius: '6px' }
});

Key Takeaway

❌ Don't need to use if:
   → Auto-enhancement is enabled (Option A or B from Method 1)
   → You created the element with createElement.bulk()
   → You created the element with createElement(tag, config)

✅ Use it when:
   → You have a plain element and need .update() on it
   → You can't enable global auto-enhancement

Method 6: Query Existing Elements (Auto-Enhanced)

What Is It?

Elements that already exist in your HTML — written as static HTML in your .html file — are automatically enhanced with .update() when accessed through Dom Helpers' Elements, Collections, or Selector helpers.

When to Use It

This is not really "creating" elements — it is accessing them. It belongs in this list because it is a complete workflow: HTML defines the structure, Dom Helpers accesses and enhances it.

How It Works

When you access an element through Elements.someId, the Elements helper:

  1. Finds the element in the DOM
  2. Attaches .update() to it
  3. Returns the enhanced element

Same for Collections.ClassName.myClass and Selector.query('.my-selector').

Examples

javascript
// HTML in your file:
// <div id="myDiv">I already exist in HTML</div>
// <button id="submitBtn">Submit</button>

// Access through Elements — automatically enhanced
const myDiv = Elements.myDiv;

// .update() is available
myDiv.update({
  textContent: 'Updated from JavaScript!',
  style: { background: '#e3f2fd' }
});

// Collections are also enhanced
Collections.ClassName.card.forEach(cardEl => {
  cardEl.update({
    classList: { add: ['animated'] }
  });
});

// Selector results are enhanced
const activeButton = Selector.query('.btn.active');
activeButton.update({
  disabled: true,
  textContent: 'Processing...'
});

The Philosophy Behind Method 6

This method represents Dom Helpers' core principle: HTML stays in HTML, JavaScript enhances it.

HTML file:
<nav id="mainNav">...</nav>        ← Structure defined in HTML
<button id="loginBtn">Login</button>   ← Static elements in HTML

JavaScript:
Elements.mainNav.update({ ... })   ← Behavior added via JS
Elements.loginBtn.update({ ... })  ← Enhancement applied

You keep the separation of concerns clean. HTML is not buried inside JavaScript strings. JavaScript does not duplicate the page structure.


Method 7: Clone Existing Elements

What Is It?

Browser's native cloneNode(true) duplicates an existing element and all its children. Since the clone is a fresh copy, it does not inherit Dom Helpers enhancement — you need to re-enhance it manually.

When to Use It

  • You need multiple copies of the same element structure
  • The element was originally created with complex styling or structure that you want to replicate
  • You are implementing a "duplicate" feature in a UI

Syntax

javascript
const original = Elements.myElement;
const clone = original.cloneNode(true);  // true = deep clone (includes children)

// Re-enhance the clone
EnhancedUpdateUtility.enhanceElementWithUpdate(clone);

// Now use .update() on the clone
clone.update({
  id: 'cloned-element',
  textContent: 'I am a clone!'
});

Elements.container.appendChild(clone);

Full Example

javascript
// HTML:
// <div id="cardTemplate" class="card hidden">
//   <h3>Template Title</h3>
//   <p>Template description</p>
// </div>

function duplicateCard(title, description) {
  const template = Elements.cardTemplate;
  const clone = template.cloneNode(true);

  // Re-enhance the clone for .update() support
  EnhancedUpdateUtility.enhanceElementWithUpdate(clone);

  // Remove the template's ID and hidden class
  clone.update({
    id: `card-${Date.now()}`,
    classList: { remove: ['hidden'] }
  });

  // Update the cloned children
  clone.querySelector('h3').textContent = title;
  clone.querySelector('p').textContent = description;

  return clone;
}

Elements.cardGrid.appendChild(duplicateCard('Product A', 'Great product'));
Elements.cardGrid.appendChild(duplicateCard('Product B', 'Even better'));

Key Insight About Cloning

original = enhanced element with .update() ✅
clone = fresh copy WITHOUT .update() ❌

After EnhancedUpdateUtility.enhanceElementWithUpdate(clone):
clone = enhanced with .update() ✅

Always re-enhance after cloning if you need .update().


Method 10: Batch Creation with Loop

What Is It?

Method 10 is the pattern of programmatically building the configuration object before passing it to createElement.bulk() — typically using a loop over an array of data.

When to Use It

  • You have an array of data items and need one element per item
  • The number of items is not known at write time (it comes from an API, user input, etc.)
  • You want to use the full createElement.bulk() result object with dynamic data

How It Works

1️⃣  Start with an empty config object {}
2️⃣  Loop over your data array
3️⃣  For each item, add a key to the config object
4️⃣  Pass the complete config to createElement.bulk()
5️⃣  Work with the result object

Example: Dynamic List

javascript
const menuItems = ['Dashboard', 'Analytics', 'Reports', 'Settings', 'Help'];

// Build config dynamically
const config = {};
menuItems.forEach((label, index) => {
  config[`LI_${index + 1}`] = {
    textContent: label,
    classList: { add: ['nav-item'] },
    addEventListener: ['click', () => navigateTo(label.toLowerCase())]
  };
});

// Create all items at once
const navItems = createElement.bulk(config);

// Append all
navItems.appendTo(Elements.mainNav);

Example: Product Grid from API Data

javascript
async function renderProducts() {
  const products = await fetchProducts();  // Returns array of product objects

  // Build definitions from API data
  const definitions = {};
  products.forEach((product, i) => {
    definitions[`CARD_${i + 1}`] = {
      className: 'product-card',
      dataset: { productId: String(product.id) },
      innerHTML: `
        <img src="${product.image}" alt="${product.name}">
        <h3>${product.name}</h3>
        <p class="price">$${product.price}</p>
      `,
      addEventListener: ['click', () => openProduct(product.id)]
    };
  });

  const cards = createElement.bulk(definitions);

  // Count and log
  console.log(`Rendered ${cards.count} products`);

  // Append all
  cards.appendTo(Elements.productGrid);
}

Using reduce for Cleaner Syntax

javascript
const tags = ['JavaScript', 'CSS', 'HTML', 'DOM', 'APIs'];

// Build config with reduce
const tagConfig = tags.reduce((config, tag, index) => {
  config[`SPAN_${index + 1}`] = {
    textContent: tag,
    classList: { add: ['tag'] },
    style: { margin: '4px', padding: '4px 10px', background: '#e3f2fd', borderRadius: '12px' }
  };
  return config;
}, {});

const tagElements = createElement.bulk(tagConfig);
tagElements.appendTo(Elements.tagCloud);

Method 10 vs Numbered Instances (Method 4)

That is a very good question — here is the distinction:

Method 4 (Numbered Instances)Method 10 (Loop-Based)
Number of elements is known at write timeNumber of elements comes from data
Configuration written directly in source codeConfiguration built programmatically in a loop
DIV_1, DIV_2, DIV_3 written by handDIV_${index} generated by loop
Best for: static, fixed-count groupsBest for: dynamic, data-driven lists

In practice: Method 4 for fixed, known-at-write-time groups; Method 10 for dynamic data.


Method 12: Conditional Element Creation

What Is It?

Method 12 is the pattern of conditionally including or excluding elements from the configuration object before passing it to createElement.bulk().

When to Use It

  • Different user roles need different UI elements (admin vs regular user)
  • UI elements appear only when certain feature flags are enabled
  • Optional elements that depend on data availability
  • Dynamic UI that changes shape based on application state

How It Works

1️⃣  Start with a base config object (elements always present)
2️⃣  Add optional keys to the config based on conditions
3️⃣  Pass the config to createElement.bulk()
4️⃣  Use elements.has() to safely access optional elements

Example: Admin Dashboard

javascript
function buildDashboard(user) {
  // Base elements — always present
  const config = {
    HEADER: {
      innerHTML: `<h1>Welcome, ${user.name}</h1>`,
      className: 'dashboard-header'
    },
    CONTENT: {
      className: 'dashboard-content'
    }
  };

  // Conditional: only admins see the admin panel
  if (user.role === 'admin') {
    config.ADMIN_PANEL = {
      className: 'admin-panel',
      innerHTML: '<h2>Admin Controls</h2><p>Manage users, settings, and data.</p>',
      style: { background: '#fff3cd', padding: '20px', borderRadius: '8px' }
    };
  }

  // Conditional: premium badge for premium users
  if (user.isPremium) {
    config.PREMIUM_BADGE = {
      textContent: '⭐ Premium Member',
      style: {
        display: 'inline-block',
        padding: '4px 12px',
        background: 'gold',
        color: '#333',
        borderRadius: '20px',
        fontWeight: '600',
        fontSize: '0.85rem'
      }
    };
  }

  // Conditional: email verified notice
  if (!user.emailVerified) {
    config.VERIFY_NOTICE = {
      textContent: 'Please verify your email address.',
      classList: { add: ['alert', 'alert-warning'] },
      style: { padding: '12px', background: '#fff3cd', borderRadius: '6px' }
    };
  }

  const dashboard = createElement.bulk(config);

  // Safely access optional elements
  if (dashboard.has('VERIFY_NOTICE')) {
    dashboard.CONTENT.prepend(dashboard.VERIFY_NOTICE);
  }
  if (dashboard.has('PREMIUM_BADGE')) {
    dashboard.HEADER.appendChild(dashboard.PREMIUM_BADGE);
  }
  if (dashboard.has('ADMIN_PANEL')) {
    dashboard.CONTENT.appendChild(dashboard.ADMIN_PANEL);
  }

  dashboard.HEADER.after(dashboard.CONTENT);

  return dashboard.HEADER;
}

Example: Notification with Optional Icon

javascript
function createNotification(message, options = {}) {
  const config = {
    DIV: {
      className: 'notification',
      style: {
        display: 'flex',
        alignItems: 'center',
        gap: '10px',
        padding: '12px 16px',
        background: options.background || '#e3f2fd',
        borderRadius: '8px'
      }
    },
    TEXT: {
      textContent: message,
      style: { flex: '1' }
    }
  };

  // Add icon only if provided
  if (options.icon) {
    config.ICON = {
      textContent: options.icon,
      style: { fontSize: '1.2rem', flexShrink: '0' }
    };
  }

  // Add dismiss button only if dismissible
  if (options.dismissible) {
    config.DISMISS = {
      textContent: '×',
      style: {
        background: 'none',
        border: 'none',
        cursor: 'pointer',
        fontSize: '1.2rem',
        lineHeight: '1',
        padding: '0',
        flexShrink: '0'
      }
    };
  }

  const n = createElement.bulk(config);

  if (n.has('ICON'))    n.DIV.prepend(n.ICON);
  n.DIV.appendChild(n.TEXT);
  if (n.has('DISMISS')) {
    n.DISMISS.addEventListener('click', () => n.DIV.remove());
    n.DIV.appendChild(n.DISMISS);
  }

  return n.DIV;
}

// Various uses
Elements.messages.appendChild(
  createNotification('Welcome back!', { icon: '👋', dismissible: true })
);
Elements.messages.appendChild(
  createNotification('Server maintenance in 1 hour.', { background: '#fff3cd', icon: '⚠️' })
);
Elements.messages.appendChild(
  createNotification('Simple notification with no extras')  // No icon, no dismiss
);

Defensive Access with .has() and .get()

When elements are conditionally present, always check before accessing:

javascript
const result = createElement.bulk(conditionalConfig);

// ❌ Risky — will throw if ADMIN_PANEL doesn't exist
result.ADMIN_PANEL.style.display = 'block';

// ✅ Safe — checks existence first
if (result.has('ADMIN_PANEL')) {
  result.ADMIN_PANEL.style.display = 'block';
}

// ✅ Also safe — .get() returns null if missing
const panel = result.get('ADMIN_PANEL', null);
if (panel) {
  panel.style.display = 'block';
}

Summary: All 13 Methods at a Glance

#MethodBest For
1Auto-enhanced document.createElement()Familiar API, migration from plain JS
2createElement.bulk() — single elementDeclarative single-element with named access
3createElement.bulk() — multiple elementsCreating component structures
4Numbered instances (DIV_1, DIV_2)Multiple same-tag elements with unique keys
5Manual enhancementEnhancing external/existing elements
6Query existing (auto-enhanced)Elements already in HTML
7Clone + re-enhanceDuplicating element structures
8Factory functionsReusable element creators
9Component patternSelf-contained UI pieces
10Loop-based batch creationDynamic, data-driven element creation
11Template-basedConfiguration reuse and design consistency
12Conditional creationRole-based or state-dependent UI
13createElement(tag, config)Single element with direct reference

What's Next?