DEV Community

Boo C
Boo C

Posted on

Building an Interactive Product Search App with JavaScript and a Mock API

Introduction

As web developers in training, learning to build interactive applications that communicate with APIs is one of the most valuable skills we can develop. APIs, or Application Programming Interfaces, allow websites and applications to access and share data efficiently. For my Phase 1 project, I decided to create an interactive product search app that lets users find iPhone models, view their details, and even click images to visit external purchase links. The project uses HTML, CSS, and JavaScript, and it communicates with a local mock API powered by json-server.

This blog will walk through the purpose of the project, how it was built, the key JavaScript features used (such as event listeners, array methods, and DOM manipulation), and what I learned from the process.

  1. Purpose and Overview of the App

The main goal of this project was to build a single-page web app that interacts asynchronously with data stored in a mock API (db.json). The app allows users to search for iPhone models, view product details (including price, storage, color, and description), and toggle between light and dark modes.

The user experience is designed to be simple:
•The user types a product name (e.g., “iPhone 14”) into a
search bar.
•The app filters through the list of iPhones and displays the
matching product.
•Clicking on the image opens a purchase link in a new tab.
•A dark mode toggle lets the user switch the page theme.
All of this happens without reloading the page, thanks to asynchronous JavaScript and DOM manipulation.

  1. Setting Up the Mock API

Instead of using a public API, I created a db.json file that contains a collection of five iPhone objects. Each object includes multiple attributes such as:

{
"id": 1,
"model": "iPhone 13",
"storage": "128GB",
"price": 699,
"color": "Midnight",
"description": "The iPhone 13 offers a sleek design, improved
battery life, and the A15 Bionic chip for fast
performance.",
"image": "https://store.storeimages.cdn-apple.com/.../iphone-

13.png",
"buyLink": "https://www.apple.com/shop/buy-iphone/iphone-13"
}

Using json-server, I ran this file locally at http://localhost:3000/iphones, which acted like a real API. When the app starts, it fetches this data asynchronously using the fetch() method in JavaScript.

  1. Fetching Data Asynchronously

The first part of the JavaScript code is responsible for fetching the data:

fetch("http://localhost:3000/iphones")
.then(res => res.json())
.then(data => {
iphones = data;
});

Here’s what happens step by step:

•fetch() sends a GET request to the local API.
•The response is converted into JSON.
•The resulting data (an array of iPhones) is stored in a variable called iphones.

This allows the rest of the app to use that array to search and display results.

  1. Event Listeners: Making the App Interactive

The app uses three distinct event listeners, each with its own callback function.

a) Click Event – Dark Mode Toggle

This event switches between light and dark themes by toggling a CSS class:

toggleBtn.addEventListener("click", () => {
document.body.classList.toggle("dark-mode");
});

When the user clicks the “Dark Mode” button, JavaScript adds or removes the .dark-mode class from the

, changing the background and text colors.

b) Input Event – Live Search Suggestions

This event listens for typing in the search box and filters the available iPhones:

searchInput.addEventListener("input", () => {
const query = searchInput.value.toLowerCase().trim();
const suggestions = iphones.filter(phone =>
phone.model.toLowerCase().includes(query)
);

if (query) {
resultsDiv.innerHTML = suggestions
.map(phone => <p>${phone.model}</p>)
.join("");
} else {
resultsDiv.innerHTML = "

Start typing to search...

";
}
});

As the user types, the app filters results using the filter() method — one of JavaScript’s most useful array iteration methods.

c) Submit Event – Display Product Information

When the user submits the form, the app finds the exact match and displays detailed product info dynamically:

form.addEventListener("submit", (e) => {
e.preventDefault();
const query = searchInput.value.toLowerCase().trim();
const product = iphones.find(
iphone => iphone.model.toLowerCase() === query
);

if (product) {
resultsDiv.innerHTML =
<div class="product">
<h2>${product.model}</h2>
<img id="product-img" src="${product.image}" alt="${product.model}" width="200">
<p><strong>Storage:</strong> ${product.storage}</p>
<p><strong>Color:</strong> ${product.color}</p>
<p><strong>Price:</strong> ${product.price}</p>
<p><strong>Description:</strong> ${product.description}</p>
</div>
;

const img = document.getElementById("product-img");
img.addEventListener("click", () => {
  window.open(product.buyLink, "_blank");
});
Enter fullscreen mode Exit fullscreen mode

} else {
resultsDiv.innerHTML = "

No matching product found.

";
}

form.reset();
});

This feature makes the project feel like a real online shopping experience.

  1. Styling with CSS

The app’s design is clean and minimal. The CSS includes:
•A responsive layout for the search form and results.
•A dark mode theme using .dark-mode.
•A round floating button for toggling dark mode on the top-left corner.

.dark-mode {
background-color: #222;
color: #fff;
}

theme {

position: fixed;
top: 10px;
left: 10px;
border-radius: 50%;
padding: 10px;
background: #ccc;
}

  1. Challenges and Lessons Learned

One of the biggest challenges was handling different event types properly. At first, I had two click events (one for the image and one for the dark mode toggle), but that only counted as one event type. Adding an input event for live search solved this and made the app more dynamic.

I also learned how important it is to separate HTML, CSS, and JavaScript logic clearly. Using event listeners in JavaScript instead of inline HTML attributes makes the code more maintainable and readable.

Finally, understanding how asynchronous fetch() works helped me see how modern web apps load data without refreshing the page — a key concept behind single-page applications (SPAs).

  1. Conclusion

This project taught me the fundamentals of front-end web development — connecting to APIs, handling user input, and dynamically updating the DOM. Even though the API was a mock database, it accurately simulated how real-world applications communicate with data servers.

By building this app, I strengthened my understanding of:
•Asynchronous JavaScript (fetch + promises)
•Array iteration methods (filter, find, map)
•Event-driven programming
•DOM manipulation and styling

In the end, this iPhone Product Search App isn’t just a project — it’s a foundation for building more complex, real-world interactive applications. I now feel much more confident about using JavaScript to bring data-driven web pages to life.

You can view the complete source code for this project on my GitHub repository: https://github.com/Boo-coder/final-project

Top comments (0)