Skip to content

Instantly share code, notes, and snippets.

@dedemenezes
Created January 28, 2025 20:40
Show Gist options
  • Save dedemenezes/847d1e4871aae8d1a36d0f094b5cf102 to your computer and use it in GitHub Desktop.
Save dedemenezes/847d1e4871aae8d1a36d0f094b5cf102 to your computer and use it in GitHub Desktop.

Background and Objectives

Today we will build a Christmas list, just like you did back in the Intro to Ruby module, but this time it'll have a real front-end!

We will be creating a form via which we can upload gifts to our list. We will also be using an API to get gift ideas we can add to our list.

The Bootstrap stylesheet is already linked in the index.html file for you so feel free to use their pre-made classes or have a go at making your own in style.css!

Note: there will be no rake for this challenge! To see if your page is working, you'll have to test it out yourself in the browser.

1. HTML & CSS

1.1. Create a form

Form and list

Let's begin by creating our gift form. It should have the following inputs:

  1. Name
  2. Price

Use a little CSS and/or Bootstrap to make it look neat and center it in the middle of the page. Don't worry about spending too long on this; you can come back to it at the end if you want to make it look prettier 🖌️

1.2. Create list

Let's create a list and two or three hard-coded items. We will remove these shortly so we can add the items via the form; they're just there for now so we can style our list :)

2. JavaScript Form

Dynamic form and list

Let's make our form work!

2.1. Listen for a submission

At which moment do we want to add an item to our list? When we submit our form, of course!

First, select the form. Then, listen out for form submission. For now, we can just console.log('Form submitted!') when we hear it.

Note: Remember that the default behaviour of a form is that it refreshes the page unless we tell it not to!

2.2. Grab the inputs

Before we start thinking about adding things to the list, let's start off with grabbing the name and price from the form's inputs.

Remember, you first need to select each input and then you can access its value.

To check if you're accessing the right elements, you can use console.log() at each stage.

2.3. Add information from the inputs to the list

Now that we have the information from the form, lets select our list an add our gift to the end of it.

3. Fetch and API

Sometimes it's hard to think of gifts for everyone. So, let's use the Fake Store API to come up wiht some ideas! Take a minute to read the documentation before beginning.

3.1. Create a 'find ideas' form

Find ideas form

For our 'ideas' form, we want to have a dropdown with the following options:

  • Electronics
  • Jewelry
  • Men's clothing
  • Women's clothing

Important: It doesn't matter if you have the text displayed in the options capitalised or not, but the value of each one must be written the same as they are here

Follow the same steps as you did for your previous form (HTML, basic CSS and listening out for a submission).

3.2. On submit, call the API

We will be making a fetch request to make a call to the API.

As there is an endpoint for each category, we will want to make sure that we can access any endpoint using the same code.

Below is some code to get you started. Don't forget that you first need to grab the user's chosen category from the input!

Below is some code that makes a call to the endpoint for the "jewelery" category. You can use this as a starting point to help you figure out how to dyanmically make calls to the API depending on the user's selected category.

fetch('https://fakestoreapi.com/products/category/jewelery')
            .then(response => response.json())
            .then(data => console.log(data))

Use console.log() to see what we got back from the API.

3.3. Display gift ideas in a list

Display gift ideas

Look carefully at what the API has given you - which information is relevant to our list? How do we access it?

Let's display the gift options in a separate list so the user can see which choices are available to them.

In a moment we'll want to make it so that we can select ideas and add them to our main list, so you can go ahead and create an "Add" button for each one.

3.4. Choose on an idea and add it to the list

Select gift ideas

Now, when a click is heard on the "Add" button of each idea, let's remove that item from the ideas list and add it the main gift list.

Optionals

Click on an item to cross it out

Select gift ideas

Already bought a gift? Great! So let's cross it off on our list.

For both the items we add via our form and also the ones that come from our ideas list, listen out for a click. Upon clicking, we want to cross the item off.

🤔 Bonus: Can you make it so that when we hover over an item, the mouse turns to a 👆🏽?

Save the list

Notice how when we refresh the page, we lose the items we added to our list. Can you store the items in localStorage as we add them and load them up when we refresh?

Improve it with JS packages

Have a go at implementing Tom Select to improve the appearance of the dropdown list.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="app-container">
<h1 class="text-center my-4">🎁🎄 Christmas List 🎄🎁</h1>
<ol id="list-items"></ol>
<div class="divider"></div>
<h2>Add a new item</h2>
<form action="#">
<div class="d-flex gap-4 align-items-end mb-3">
<div class="w-50">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control " id="gift-name">
</div>
<!-- EMMET -->
<div class="w-50">
<label for="price">Price</label>
<input type="number" class="form-control" id="gift-price">
</div>
</div>
<input type="submit" class="btn btn-success w-100">
</form>
<div class="divider"></div>
<h3>Find ideas! 💡</h3>
<ol id="suggestions"></ol>
<!--
<select name="" id="">
<option value="important-text">USer friendly text</option>
</select>
-->
<form action="#" id="search-form">
<label>What would you like to search for?</label>
<div class="d-flex align-items-center gap-2 mt-2">
<select class="form-select w-75" id="search-input">
<option value="electronics">Electronic</option>
<option value="jewelery">Jewelery</option>
<option value="men's clothing">Men's clothing</option>
<option value="women's clothing">Women's clothing</option>
</select>
<input type="submit" class="w-25 btn btn-success" value="Search">
</div>
</form>
</div>
<script src="index.js"></script>
</body>
</html>
// Select the necessary elements for adding an item to the list via the new form
const form = document.querySelector('form');
const listItems = document.getElementById('list-items');
const giftNameInput = document.getElementById('gift-name');
const giftPriceInput = document.getElementById('gift-price');
// Select the necessary elements for adding an item to the list via the ideas form
const searchForm = document.querySelector('#search-form');
const suggestionList = document.querySelector('#suggestions');
const searchInput = document.querySelector('#search-input');
// We can REMOVEE THIS NOW!
// const items = [
// { name: 'Chocolate', price: 4 },
// { name: 'Cake', price: 6 }
// ];
// items.forEach((item) => {
// const giftListElement = `<li>${item.name} - ${item.price}</li>`;
// listItems.insertAdjacentHTML('beforeend', giftListElement);
// });
const addNewGiftFromSuggestion = (e) => {
const item = e.currentTarget.parentElement;
// 2. Add it to the gift list
listItems.appendChild(item);
// 1. Remove the button from the suggestion
e.currentTarget.remove();
};
const handleNewGiftForm = (event) => {
// Prevent the default behavior
event.preventDefault();
// Extract 'name' and 'price' from input values
const giftName = giftNameInput.value;
const giftPrice = giftPriceInput.value;
// Create the list item
const userListItem = `<li>${giftName} - ${giftPrice}</li>`;
// Add to the ordered list
listItems.insertAdjacentHTML('beforeend', userListItem);
// Clean the input
giftNameInput.value = "";
giftPriceInput.value = "";
};
// listen to submit on new form
form.addEventListener('submit', handleNewGiftForm);
// listen to submit on search form
searchForm.addEventListener('submit', (event) => {
// avoid page refreshes
event.preventDefault();
// Clear the suggestion list
suggestionList.innerHTML = '';
// Extract selected category value
const category = searchInput.value;
// Fetch the api for the products for the specific category
fetch(`https://fakestoreapi.com/products/category/${category}`) // make http request
.then(response => response.json()) // parse the response
.then((data) => {
// iterate through each one of the objects inside the array
data.forEach((suggestion) => {
// Create the list item using createElement
const listItemElement = document.createElement('li');
// list item text must be suggestion name and price
listItemElement.innerHTML = `${suggestion.title} - ${suggestion.price}`;
// create the button element
const addButtonElement = document.createElement('button');
addButtonElement.innerText = 'Add';
addButtonElement.classList.add('btn', 'btn-info');
// appended button to list item
listItemElement.appendChild(addButtonElement);
// appended list item to the suggestion list
suggestionList.appendChild(listItemElement);
// bind the event listener
addButtonElement.addEventListener('click', addNewGiftFromSuggestion);
});
});
});
// https://stackoverflow.com/questions/34896106/attach-event-to-dynamic-elements-in-javascript/57031665#57031665
.divider {
width: 100%;
border: 0.5px solid rgba(0, 0, 0, 0.1);
margin: 20px 0;
}
.app-container {
width: 700px;
margin: auto;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment