Menu
CoddyTech

A Page That Calls the API

Part of the REST APIs section of Coddy's Node.js journey. Lesson 21 of 25.

A page calls your API with fetch. A POST needs three options: method, headers and body. Convert the JavaScript object to JSON text for the body, and label that text as application/json.

const response = await fetch('/api/books', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({title: title}),
});
const data = await response.json();

The first await receives the HTTP response. The second reads its JSON body. response.ok tells you whether its status is in the successful range. A status such as 400 or 409 does not reject the fetch promise; it gives a response whose ok is false. The form and list code are supplied; focus on sending the request and handling its result.

The supplied message variable refers to the page’s message paragraph. Set its textContent to display text, or to an empty string to clear it:

message.textContent = data.error.message;
// Clear it after success:
message.textContent = '';

The page and API share an origin, so this call needs no CORS permission. FormData encodes a form differently from JSON; use JSON text because this API uses express.json().

challenge icon

Challenge

Easy

Your API has no screen yet. Give it a small page, served by the same server, whose form adds tasks through the API.

  1. In server.js, serve the public folder with express.static, so GET / returns public/index.html.
  2. In public/index.html, the submit listener already reads the title. Make it send the new task to the API:
    • Use the supplied title variable containing the input text.
    • Send it with fetch('/api/tasks', ...) as a POST.
    • The body is JSON text made with JSON.stringify, like {"title":"Water the plants"}.
    • The request needs the header 'Content-Type': 'application/json', in fetch's headers option, or express.json() will not read the body.
  3. If the response is OK (its ok property is true for any status from 200 to 299), clear the form with form.reset(), empty #message, and call load() so the list shows the new task.
  4. Otherwise the response body is the error shape from earlier, for example:
    { "error": { "code": "conflict", "message": "A task with this title already exists" } }
    Show its message in the #message paragraph.

The checks execute this supplied page script with a small simulated form and the real lesson API. They submit a task and a duplicate, then inspect the list, form and message. Also try the actual page beside the editor.

Try it: send GET /. The page opens in the page view with the 3 starting tasks. Type "Water the plants" and press Add: the input empties and the task appears at the bottom of the list. Type "Water the plants" again and press Add: the list stays the same, and "A task with this title already exists" appears under the form.

Try it yourself

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Tasks</title>
</head>
<body>
    <h1>Tasks</h1>
    <ul id="list"></ul>
    <form id="add">
        <input name="title" placeholder="New task" required>
        <button>Add</button>
    </form>
    <p id="message"></p>
    <script>
        const list = document.querySelector('#list');
        const form = document.querySelector('#add');
        const message = document.querySelector('#message');

        async function load() {
            const response = await fetch('/api/tasks?limit=50');
            const page = await response.json();
            list.replaceChildren(...page.items.map((task) => {
                const item = document.createElement('li');
                item.textContent = (task.done ? '[x] ' : '[ ] ') + task.title;
                return item;
            }));
        }

        form.addEventListener('submit', async (event) => {
            event.preventDefault();
            const title = form.elements.title.value;
            // Send the title to POST /api/tasks as JSON. On success clear
            // the form and load() again; on an error show its message.
        });

        load();
    </script>
</body>
</html>

All lessons in REST APIs

Practice on your own: Express playground