20. Advanced DOM Manipulation with APIs
Why Advanced DOM + API Skills Matter
Fetching data from APIs is only useful if you can present it dynamically in your web page. Advanced DOM manipulation allows you to create, update, and remove elements in real time based on API responses.
Creating Elements Dynamically
You can use `document.createElement` and `appendChild` to inject data-driven content into the page.
const container = document.getElementById('userContainer');
const user = { name: 'Alice', age: 25 };
const card = document.createElement('div');
card.classList.add('user-card');
card.innerHTML = `<h3>${user.name}</h3><p>Age: ${user.age}</p>`;
container.appendChild(card);Updating Elements Based on API Data
After fetching data, you can update existing DOM elements dynamically without reloading the page.
async function updateUserList() {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await res.json();
const list = document.getElementById('userList');
list.innerHTML = ''; // Clear existing
users.forEach(user => {
const li = document.createElement('li');
li.textContent = `${user.name} (${user.email})`;
list.appendChild(li);
});
}
updateUserList();Event-Driven Updates
Use event listeners to fetch and display data in response to user interactions like clicks, input changes, or form submissions.
document.getElementById('loadUsersBtn').addEventListener('click', async () => {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await res.json();
const list = document.getElementById('userList');
list.innerHTML = '';
users.forEach(user => {
const li = document.createElement('li');
li.textContent = `${user.name} — ${user.email}`;
list.appendChild(li);
});
});Templating and Fragments
Use `DocumentFragment` or template literals for efficient DOM updates, especially for large datasets.
async function renderUsers() {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await res.json();
const fragment = document.createDocumentFragment();
users.forEach(user => {
const li = document.createElement('li');
li.textContent = `${user.name} — ${user.email}`;
fragment.appendChild(li);
});
document.getElementById('userList').appendChild(fragment);
}
renderUsers();Handling Loading States and Errors
Show users that data is loading, and display meaningful error messages if something goes wrong.
async function fetchAndRenderUsers() {
const list = document.getElementById('userList');
list.textContent = 'Loading...';
try {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
if (!res.ok) throw new Error('Failed to fetch users');
const users = await res.json();
list.innerHTML = '';
users.forEach(user => {
const li = document.createElement('li');
li.textContent = `${user.name} — ${user.email}`;
list.appendChild(li);
});
} catch (err) {
list.textContent = `Error: ${err.message}`;
}
}
fetchAndRenderUsers();Mini Challenge
1. Create a search input where users can type a name. Fetch users from an API and display only matching results. 2. Add a loading spinner while fetching. 3. Gracefully handle errors and empty results. 4. Bonus: Highlight the matched text in the results.