Free tutorials & notes in Hindi & English · Clean code examples 🧰 Free PDF & Image Tools →
🖱️ Days 8–14 – Data, DOM & Events  ·  Day 12

Day 12: Create Elements & Render Lists from Data

⏱ 95 min📶 Intermediate🎯 100% self-study
Day 12 / 30

✅ Today you will learn

  • createElement, append, prepend, before, after, remove
  • Rendering a product grid from an array of objects
  • Template literals vs createElement vs <template>
  • DocumentFragment for fast batch inserts
  • State → render() → UI: the pattern React is built on

🏢 In the real world

The menu changes every day: new sweets, sold-out items, price updates. Editing HTML by hand each morning is impossible. Real websites keep products as data (from a database or API) and generate the HTML with JavaScript. Today you build the Sharma Sweets product grid from an array – the same technique tomorrow’s API data will use.

Creating and inserting elements

HTML + JavaScript
<ul id="list"><li>Kaju Katli</li></ul>
<button id="add">append</button> <button id="first">prepend</button> <button id="del">remove last</button>

<script>
const list = document.querySelector('#list');

document.querySelector('#add').addEventListener('click', () => {
  const li = document.createElement('li');          // 1. create
  li.textContent = 'Ghewar ' + (list.children.length + 1);   // 2. fill (safe text)
  li.className = 'new';
  list.append(li);                                   // 3. insert at the end
});
document.querySelector('#first').addEventListener('click', () => {
  const li = document.createElement('li');
  li.textContent = '⭐ Today’s special';
  list.prepend(li);                                  // insert at the start
});
document.querySelector('#del').addEventListener('click', () => {
  list.lastElementChild?.remove();                  // remove (?. = only if it exists)
});
</script>
▶  createElement → set content → append/prepend → remove
MethodPuts the node…
parent.append(node, "text")At the end inside parent (several at once)
parent.prepend(node)At the start inside parent
el.before(node) / el.after(node)Just outside el, before or after it
el.replaceWith(node)Instead of el
el.remove()Deletes el
parent.replaceChildren(...nodes)Clears parent and inserts the new nodes – perfect for re-rendering

Render a product grid from data

HTML + JavaScript
<style>
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.card { border: 1px solid #e5e7eb; border-radius: 12px; overflow: hidden; background: #fff; }
.card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.card div { padding: 8px 10px; }
.card button { width: 100%; margin-top: 6px; }
.card.out { opacity: .55; }
</style>

<div class="grid" id="grid"></div>

<script>
const products = [
  { id: 1, name: 'Kaju Katli',   price: 900, image: 'images/kaju-katli-400.webp', stock: 25 },
  { id: 2, name: 'Malai Ghewar', price: 650, image: 'images/ghewar-400.webp',     stock: 8 },
  { id: 3, name: 'Rasmalai',     price: 700, image: 'images/rasmalai-400.webp',   stock: 0 },
  { id: 4, name: 'Besan Ladoo',  price: 500, image: 'images/ladoo-400.webp',      stock: 40 },
];

function createCard(p) {
  const card = document.createElement('article');
  card.className = 'card' + (p.stock === 0 ? ' out' : '');
  const img = document.createElement('img');
  img.src = p.image;
  img.alt = p.name;
  img.loading = 'lazy';
  const body = document.createElement('div');
  const title = document.createElement('b');
  title.textContent = p.name;                        // text is always safe
  const price = document.createElement('div');
  price.textContent = `₹${p.price}/kg`;
  const btn = document.createElement('button');
  btn.textContent = p.stock === 0 ? 'Sold out' : 'Add to cart';
  btn.disabled = p.stock === 0;
  btn.dataset.id = p.id;
  body.append(title, price, btn);
  card.append(img, body);
  return card;
}

document.querySelector('#grid').replaceChildren(...products.map(createCard));
</script>
▶  Every card is created from one object – change the data, the page follows

Three ways to build HTML from data

TechniqueProsCons
Template literal + innerHTMLShort and readableXSS risk with user data; replaces listeners inside
createElement ⭐Safe (textContent), preciseMore lines
<template> + cloneNodeHTML stays in HTML, safe fillingNeeds a template in the page
Frameworks (React, Vue)Automatic efficient updatesLearn after vanilla JS
HTML + JavaScript
<template id="row">
  <tr><td class="name"></td><td class="qty"></td><td class="amount"></td></tr>
</template>
<table border="1" cellpadding="6" style="border-collapse:collapse">
  <thead><tr><th>Item</th><th>Qty</th><th>Amount</th></tr></thead>
  <tbody id="body"></tbody>
</table>

<script>
const lines = [
  { name: 'Kaju Katli', qty: 2, price: 900 },
  { name: 'Rasmalai', qty: 1, price: 700 },
];
const tpl = document.querySelector('#row');
const fragment = document.createDocumentFragment();     // build off-screen
for (const line of lines) {
  const row = tpl.content.cloneNode(true);
  row.querySelector('.name').textContent = line.name;
  row.querySelector('.qty').textContent = line.qty + ' kg';
  row.querySelector('.amount').textContent = '₹' + line.qty * line.price;
  fragment.append(row);
}
document.querySelector('#body').append(fragment);        // ONE insert into the page
</script>
▶  &lt;template&gt; + DocumentFragment: HTML in HTML, one DOM update

State → render() → UI

State: the data (array of products, cart)Event: user clicks “Add”Update the state (never the DOM directly)Call render(state)UI rebuilt from state – always consistent
One direction, no confusion
HTML + JavaScript
<style>
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.card { border: 1px solid #e5e7eb; border-radius: 12px; overflow: hidden; background: #fff; }
.card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.card div { padding: 8px 10px; }
.card button { width: 100%; margin-top: 6px; }
.card.out { opacity: .55; }
</style>

<div class="grid" id="grid"></div>
<p id="cart"><b>Cart:</b> empty</p>

<script>
const products = [
  { id: 1, name: 'Kaju Katli',   price: 900, image: 'images/kaju-katli-400.webp', stock: 25 },
  { id: 2, name: 'Malai Ghewar', price: 650, image: 'images/ghewar-400.webp',     stock: 8 },
  { id: 3, name: 'Rasmalai',     price: 700, image: 'images/rasmalai-400.webp',   stock: 0 },
  { id: 4, name: 'Besan Ladoo',  price: 500, image: 'images/ladoo-400.webp',      stock: 40 },
];
const state = { cart: {} };                                // id → qty

function render() {
  const grid = document.querySelector('#grid');
  grid.innerHTML = '';
  for (const p of products) {
    const qty = state.cart[p.id] || 0;
    const card = document.createElement('article');
    card.className = 'card' + (p.stock === 0 ? ' out' : '');
    card.innerHTML = `<img src="${p.image}" alt=""><div><b></b><div>₹${p.price}/kg</div>
      <button data-id="${p.id}" ${p.stock === 0 ? 'disabled' : ''}>${qty ? 'Add more (' + qty + ')' : 'Add to cart'}</button></div>`;
    card.querySelector('b').textContent = p.name;
    grid.append(card);
  }
  const lines = products.filter(p => state.cart[p.id]).map(p => `${p.name} × ${state.cart[p.id]}`);
  const total = products.reduce((s, p) => s + (state.cart[p.id] || 0) * p.price, 0);
  document.querySelector('#cart').innerHTML = '<b>Cart:</b> ' + (lines.length ? lines.join(', ') + ` = ₹${total}` : 'empty');
}

document.querySelector('#grid').addEventListener('click', e => {      // delegation (Day 11)
  const btn = e.target.closest('button[data-id]');
  if (!btn) return;
  const id = Number(btn.dataset.id);
  state.cart[id] = (state.cart[id] || 0) + 1;                       // 1. update state
  render();                                                          // 2. re-render
});
render();
</script>
▶  A tiny cart: state object + render() + delegation
💡 This is how React thinks

In React you write setCart(...) and React calls your component (render) for you, updating only what changed. Understanding this vanilla version makes React feel natural.

🏅 Job skills unlocked today

✔ Create, insert and remove elements✔ Render lists and grids from arrays of objects✔ Use <template> and DocumentFragment✔ Structure UI code as state → render()

Practice tasks

🏋️ Practice – do it yourself

Task 1: Render a notice board from an array of notices {title, date, important}; important notices get a red “Important” badge, newest first.
Show solution
▶  Result
Task 2: Add a “Remove” button to each cart line of the mini cart above (update state, then render).
Task 3: Render a student result table from an array using <template> and show the class average in a <tfoot>.

Quick quiz

🧠 Quick Quiz – test yourself

1. document.createElement("li") …
append it to show it.
2. Clear a container and insert new nodes in one call:
Modern and safe.
3. Why use DocumentFragment?
Fewer reflows.
4. <template> content is…
Use content.cloneNode(true).
5. In the state → render pattern, a click should…
Single source of truth.

Interview corner

💼 Interview Corner

How do you efficiently add 1,000 items to the DOM?

Build them in a DocumentFragment (or build one HTML string with escaped data) and insert once, avoid reading layout properties inside the loop, and consider virtualisation (render only visible rows) for very long lists.

Why do frameworks use a render function instead of manual DOM edits?

Deriving the UI from state in one place keeps it consistent and predictable; the framework diffs the result and applies minimal DOM changes, avoiding bugs where some parts of the page forget to update.

Summary

  • createElement → fill with textContent → append/prepend; remove() to delete.
  • Render lists from arrays with map/forEach and replaceChildren.
  • <template> + DocumentFragment for clean, fast batches.
  • State → render() → UI; events update state, never the DOM directly.
➡️ Next

Day 13: forms – read values with FormData, validate like a professional and show helpful error messages.

Frequently Asked Questions

Is re-rendering the whole list slow?
For tens or hundreds of items it is instant. For thousands, update only changed rows or use a framework.
Why did the cart demo set the name with textContent after innerHTML?
The structure is our own trusted HTML; the product name could come from a database, so it is inserted as text to stay safe.
← JavaScript (30 Days)
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

Next topicDay 13: Forms, FormData & Validation Your progress: 12 / 30 (40%) · Lesson 13 / 30 Continue →

How was this lesson?

Your feedback helps us make the content better.

Write a review or suggestion (optional)

After approval, your name and city may appear publicly with your review. Please do not write your email or phone number.

▶ CodingEasily on YouTube

Learn with video lessons in easy Hindi

Featured video: RDBMS Part 3 – Class XI Commerce IT

▶ Subscribe – it’s free