-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
87: Practice Exercise: Building a Dynamic Table Renderer
Up until now, we've talked about manipulating individual elements. But in the real world, you're rarely just changing one piece of text. You're usually taking a chunk of data—like a JSON response from an API—and turning it into a visual list or a table. I want to show you how I approach building a dynamic table renderer without over-complicating things.
Setting up the inventory data
Let's imagine we're building a simple warehouse dashboard. We have an array of product objects. I'm keeping this simple: just a name, a quantity, and a price. In a real app, this would come from a database, but for now, we'll hardcode it so we can focus on the DOM logic.
const inventory = [
{ name: 'Mechanical Keyboard', qty: 12, price: 89.99 },
{ name: 'Logitech Mouse', qty: 45, price: 49.50 },
{ name: 'UltraWide Monitor', qty: 7, price: 320.00 },
{ name: 'USB-C Hub', qty: 22, price: 25.00 }
];
Generating the rows with map()
I could use a for loop here, but .map() is much more elegant for this. I want to transform each object in that array into a string of HTML. I'll use template literals because they make the code readable—I can actually see what the table row looks like inside the JavaScript.
function renderTable(data) {
const tableBody = document.getElementById('inventory-body');
const rows = data.map(item => `
<tr>
<td>${item.name}</td>
<td>${item.qty}</td>
<td>$${item.price.toFixed(2)}</td>
</tr>
`).join('');
tableBody.innerHTML = rows;
}
Notice the .join('') at the end. Remember that .map() returns an array. If we just shoved that array into innerHTML, JavaScript would join the elements with commas by default, and we'd have random commas floating all over our table. Not a great look.
The "Infinite Growth" mistake
Here is where I usually trip up when I'm rushing. I decided to add a "Refresh" button to the UI to simulate updating the data. I wrote a function to add a new random item to the list and then called renderTable() again. But when I tested it, I noticed that every time I clicked refresh, the table didn't update—it just kept growing. The new list was being appended to the old one.
I realized I was using tableBody.innerHTML += rows; instead of tableBody.innerHTML = rows;. It's a tiny difference—one character—but a huge difference in behavior. In dynamic rendering, you almost always want to clear the container or overwrite it entirely unless you are specifically building an "infinite scroll" list. I switched back to the assignment operator, and the duplication vanished.
Handling empty states
One last thing: software is only as good as how it handles the "nothing" state. If the inventory array is empty, the table just looks like a blank void. I'll add a quick guard clause at the top of the function. If there's no data, I'll just inject a single row telling the user the warehouse is empty. It's a small touch, but it's what separates a "coding exercise" from a professional feature.
function renderTable(data) {
const tableBody = document.getElementById('inventory-body');
if (data.length === 0) {
tableBody.innerHTML = '<tr><td colspan="3">No stock available</td></tr>';
return;
}
const rows = data.map(item => `
<tr>
<td>${item.name}</td>
<td>${item.qty}</td>
<td>$${item.price.toFixed(2)}</td>
</tr>
`).join('');
tableBody.innerHTML = rows;
}📋 Practical Task
Exercise: Building a User Permissions Auditor Table
You need to build a dynamic table that displays a list of users and their access levels. This is for an internal security tool, so accuracy is key.
Requirements:
- Create an array of objects called
users. Each object should have ausername, arole(e.g., 'Admin', 'Editor', 'Viewer'), and alastLogindate. - Write a function
renderUserTable(userData)that targets a<tbody>element with the IDuser-table-body. - Use
.map()to generate the rows. - Logic Challenge: If a user's role is 'Admin', wrap the role text in a
<strong>tag to make it bold. - Ensure that if the
usersarray is empty, the table displays a row saying "No users found in the system." - Verify that calling the function multiple times replaces the content rather than appending it.
There are no comments for now.