Suppose an API returns:

[
    {
        "name": "John",
        "email": "[email protected]"
    },
    {
        "name": "David",
        "email": "[email protected]"
    }
]

We can dynamically create HTML.


HTML:

<div id="users"></div>


JavaScript:

const usersContainer =
    document.querySelector("#users");

function displayUsers(users) {

    usersContainer.innerHTML = "";

    users.forEach(user => {

        const card = document.createElement("div");

        card.innerHTML = `
            <h2>${user.name}</h2>
            <p>${user.email}</p>
        `;

        usersContainer.appendChild(card);

    });
}


Complete API + Dynamic UI Example

HTML

<!DOCTYPE html>
<html>

<head>
    <title>Users</title>
</head>

<body>

    <button id="loadUsers">
        Load Users
    </button>

    <div id="users"></div>

    <script src="script.js"></script>

</body>

</html>


JavaScript

// Select the button from HTML using its ID

const button = document.querySelector("#loadUsers");


// Select the div where we want to display users

const usersContainer = document.querySelector("#users");


// When the button is clicked,
// call the loadUsers() function

button.addEventListener("click", loadUsers);


// Create an async function to load users from the API

async function loadUsers() {

    // Show a loading message while waiting for the API response
    usersContainer.textContent = "Loading...";

    // try block contains the code that may cause an error
    try {


        // Send a GET request to the API
        // await waits until the server sends a response
        const response = await fetch(
            "https://jsonplaceholder.typicode.com/users"
        );

        // Check whether the API request was successful
        // response.ok is true for successful HTTP responses
        if (!response.ok) {


            // If the request failed,
            // create an error
            throw new Error("Failed to load users");
        }

        // Convert the API response from JSON into JavaScript data
        // The result will be an array of users
        const users = await response.json();

        // Clear the "Loading..." message
        // before displaying the users
        usersContainer.innerHTML = "";

        // Loop through every user in the users array
        users.forEach(user => {


            // Create a new <div> element for each user
            const card = document.createElement("div");

            // Add HTML content inside the newly created div
            // ${user.name} gets the user's name
            // ${user.email} gets the user's email
            // ${user.address.city} gets the user's city
            card.innerHTML = `
                <h2>${user.name}</h2>
                <p>${user.email}</p>
                <p>${user.address.city}</p>
            `;

            // Add the newly created card
            // inside the usersContainer
            usersContainer.appendChild(card);


        });


    }


    // If something goes wrong inside the try block,
    // the catch block will execute
    catch (error) {


        // Show an error message to the user
        usersContainer.textContent =
            "Unable to load users.";


        // Show the actual error in the browser console
        // Useful for developers when debugging
        console.error(error);


    }
}