Last Updated on February 12, 2024
Often, The Odin project will link out to other resources for reading material and active coding assignments. This was one of those times. This one came from MDN Web Docs. The initial HTML was provided for us. I only made a couple of changes to it. Most of the work I did was in JavaScript.
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shopping list example</title>
<style>
li {
margin-bottom: 10px;
}
li button {
font-size: 8px;
margin-left: 20px;
color: #666;
}
</style>
</head>
<body>
<h1>My shopping list</h1>
<div>
<label for="item">Enter a new item:</label>
<input type="text" name="item" id="item">
<button>Add item</button>
</div>
<ul>
</ul>
<script>
</script>
</body>
</html>
The goal of this assignment was to create a shopping list where the user inputs items in the text box, click the button and have the items show up in an unordered list below. We were also meant to add delete buttons alongside each list item that would then remove the entire list item when clicked.
Getting the items to delete themselves was one of the more challenging aspects of this program. At first, I tried to add an event listener on the delete buttons outside the addToList
function, when really, it needed to be inside the function. I had a similar problem the list items. I tried initializing them with the other variables outside the addToList
function, but that meant that every new input would replace the last rather than being appended to the existing list.
The other challenge I had with the delete button was getting it to reference the entire list item that it was a part of. I’ll admit that this was one of those times where I needed some outside help. Typically, removeChild
references the first instance of a first level child. However, I needed to get to the parent of the delete button which was the list item. I knew I needed to reference the list item, but I had no idea how to reference it when it was being dynamically created by the user (creating the event listener within addToList
solved part of this problem).
At first I tried creating dynamic ids and then referencing those ids, but there were a couple issues with this method. One, I needed to figure out adding unique ids that wouldn’t conflict with each other and two, I still needed to figure out dynamically referencing those ids. In terms of the first issue, I saw some stuff on UUIDs, but I honestly did not have the patience to figure that out. And in terms of the second, I realized I was just adding extra steps to what would essentially be the same problem.
What I finally learned was that when a delete button was clicked, it needed to dynamically identify its parent and then from there reference the grandparent element that would then be able to remove the parent. A stunningly simple and elegant solution, if I ever saw one. No need to create new potentially complex or conflicting IDs, and no need to add a class to the buttons (yeah, that was something I tried lol).
function deleteFromList(){
const parent = this.parentElement;
parent.parentElement.removeChild(parent);
}
I also did a little extra. The assignment only called for the clicking of the button to add items. I’m a bit of a completionist, though, and really wanted the Enter key to trigger adding items to the list, because that is something we have come to expect as users.
At first what I tried is something I implemented in the Resume Builder – the submit event. I needed to add all the HTML to a form element, though and change the input button to a submit type. That technically worked, but it also was causing the list items to disappear as soon as they were added. My guess is that the input button was acting like a delete button too.
Once again, I really didn’t have the patience to figure out what the issue was, so I opted instead to simply create an anonymous function that responded to the enter key being pressed that then called addToList
. Successfully using the submit event would have been cleaner, but hey if it works, it works. Here is that bit of code:
input.addEventListener('keypress', function(e){
if(e.key === 'Enter'){
addToList();
}
});
Below is the complete code as well as a little results box that you can play around with the results in! Hosted by the lovely JSFiddle. Enjoy!