This mini project is designed to practice working with REST APIs using real HTTP requests. The application is built on top of the JSONPlaceholder API and demonstrates CRUD operations, pagination, query parameters, and error handling in a practical way.
- Manage users and posts using the JSONPlaceholder API
- Practice CRUD operations in a real-world scenario
- Understand pagination and query parameters
- Handle asynchronous requests and errors properly
- HTTP / HTTPS — Communication with backend APIs
- REST API — Working with
/usersand/postsendpoints - Axios — Sending HTTP requests
- CRUD Operations — Create, Read, Update, Delete
- Query Parameters — Filtering and pagination
- async / await — Asynchronous programming
- try / catch — Error handling
- Browser DevTools (Network tab) — Request inspection
- "Load Users" button fetches data from
/users - Displays user name, email, and company information
- Initially loads 5 posts
- "Load More" button implements pagination using
_limitand_page - New posts are appended to the existing list
- Simple form with
titleandbodyfields - Sends a POST request to
/posts - On success, the new post is added to the UI
- Each post contains an Edit button
- Uses PATCH request to update post content
- Delete button removes the post
- Sends a DELETE request to the API
- Deleted post is removed from the interface
- All async requests are wrapped with
try / catch - User-friendly error messages are shown using
alertoriziToast
/project ├── index.html ├── style.css └── app.js
<body>
<button id="load-users">Load Users</button>
<ul id="user-list"></ul>
<h2>Posts</h2>
<button id="load-posts">Load Posts</button>
<ul id="post-list"></ul>
<button id="load-more">Load More</button>
<h2>New Post</h2>
<form id="post-form">
<input type="text" name="title" placeholder="Title" required />
<textarea name="body" placeholder="Content" required></textarea>
<button type="submit">Add</button>
</form>
</body>
import axios from "https://cdn.jsdelivr.net/npm/axios@1.6.7/dist/axios.min.js";
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com";
// Load users
document.querySelector("#load-users").addEventListener("click", async () => {
try {
const res = await axios.get("/users");
const markup = res.data
.map(user => `<li>${user.name} - ${user.email}</li>`)
.join("");
document.querySelector("#user-list").innerHTML = markup;
} catch (error) {
alert("Failed to load users");
}
});
// Pagination for posts
let page = 1;
const limit = 5;
async function loadPosts() {
try {
const res = await axios.get("/posts", {
params: { _limit: limit, _page: page }
});
const markup = res.data
.map(post => `
<li>
<b>${post.title}</b>
<p>${post.body}</p>
</li>
`)
.join("");
document
.querySelector("#post-list")
.insertAdjacentHTML("beforeend", markup);
page++;
} catch (error) {
alert("Failed to load posts");
}
}
document.querySelector("#load-posts").addEventListener("click", loadPosts);
document.querySelector("#load-more").addEventListener("click", loadPosts);
// Create new post
document.querySelector("#post-form").addEventListener("submit", async (e) => {
e.preventDefault();
const form = e.target;
const newPost = {
title: form.title.value,
body: form.body.value,
};
try {
await axios.post("/posts", newPost, {
headers: { "Content-Type": "application/json" },
});
alert("Post successfully created!");
form.reset();
} catch (error) {
alert("Failed to create post");
}
});
This mini project brings together all essential backend interaction concepts: HTTP requests, REST architecture, CRUD operations, pagination, and error handling. It serves as a solid foundation for building more complex front-end applications that communicate with real APIs.
Happy coding! 🚀