Prep 6: Forms, Functions, Events, and localStorage
Textbook++ Reading
- HTML/CSS
- 5.4 Form Control Elements
- 5.5 Table and Form Accessibility
- 5.6 Styling and Designing Forms
- JS
- 8.9 Scope and Closures in JavaScript
- 9.4 Event Types
- 9.5 Forms in JavaScript
- 🌐 LocalStorage, sessionStorage (The Modern JavaScript Tutorial)
Better Grocery List
Our goal this time is to enhance our grocery list app from Lab 4! We’ll be making it look nicer and, most importantly, making the list persist across page reloads using localStorage.
Getting Started
First, please download and extract the prep06.zip starter code into a prep06 folder somewhere safe (like your cs343 folder). This is a slightly updated version of the solution from Lab 4.
Open the three files in VS Code. Use the live preview to open grocery.html.
Part 1: Form Control Elements
Let’s add a new drop-down menu to select the category of each grocery item, and also let the notes input span multiple rows.

- In
grocery.html, add a drop-down menu to the form (don’t forget a label!). Give it the idcategorySelectand the namecategory. It should have the six following options:- Produce
- Dairy
- Poultry
- Meat
- Pantry
- Other
- Add a new column header to the table for “Category”.
- Don’t forget to add the
scopeattribute to the header cell for accessibility! - If you want to update the example rows with categories, feel free to do so (so that the table looks nicer)
- Don’t forget to add the
- In
grocery-script.js, update theaddItemToList()function to get the category input and its value. - In
makeRow(), create a new cell for the category and append it to the row. - Back in
grocery.html, update the form so that the notes input is a<textarea>instead of an<input>.- Set the number of rows to
4.
- Set the number of rows to
- Test it out! You should be able to add items with categories and see them appear in the table.
Part 2: Styling the Form
The form is functional, but ugly. Let’s style it up to look like this:

- First, in
grocery-styles.css, let’s modify the rules forform-container:- Set its width to
fit-contentso that it wraps tightly around the form. - Also give it
5pxof vertical padding and10pxof horizontal padding.
- Set its width to
-
Now, write a new CSS rule with a single selector to select the controls for:
- the category
- the item
- the quantity
- the notes
- (but NOT the submit button!)
Hint
Don’t forget that you can use commas to select multiple elements in a single rule!
You can easily select the elements to style either by their ids or by their types.
-
In that rule, do the following:
- Add the properties to style them like the inputs in Figure 5.31 from the textbook
- Including the bottom border too! (but not the placeholder)
- See the image above for a reference
- In addition, add a declaration to set the width to
300pxso that they are all the same width. - But wait! They’re not the same width because of how the box model works.
- Add another declaration to set the
box-sizing: border-box;to fix this issue.
- Add another declaration to set the
- Add the properties to style them like the inputs in Figure 5.31 from the textbook
-
Style the submit button to look like the “Click” button in Figure 5.31 from the textbook.
-
Style the form’s labels so that they match the “Vertical” layout in Figure 5.32 from the textbook.
- They should each be on their own line, above their corresponding control.
-
Make sure you are previewing your changes. The form should now look like the second image above!
Part 3: Saving and Loading from localStorage
Right now, refreshing the page makes any added list items disappear. Let’s fix that by persisting the list to localStorage:

(Note: the above image is from Chrome/Edge DevTools. Firefox uses a “Storage” tab instead of “Application”.)
- In
grocery-script.js, implement theappendToSavedList()function.- Take a look at how we first need to parse the saved list from localStorage if it exists.
- The list is an array, saved in
localStorageas a string with the key"items".
- The list is an array, saved in
- Remember: everything in
localStorageis stored as a string!- We use
JSON.stringify(...)andJSON.parse(...)to convert between strings and arrays/objects.
- We use
- Write code to perform each of the tasks outlined by the TODO comments.
- Take a look at how we first need to parse the saved list from localStorage if it exists.
- At the end of the
addItemToList()function, callappendToSavedList()with the appropriate arguments to save the new item to localStorage. - Next, implement
loadList(), which will load the saved list from localStorage and add each item to the table.- Don’t forget, the list is saved with the key
"items"in localStorage, and is stored as a stringified array. - If the key
"items"doesn’t exist, then this function should do nothing. - Write code to perform each of the tasks outlined by the TODO comments.
- Don’t forget, the list is saved with the key
- Finally, we need to call
loadList()once the page loads. Two ways to do this:- Ideally, use
document.addEventListener(...)to listen for theDOMContentLoadedevent and specify a callback function. - Alternatively, because this script is at the end of
<body>, we could also just callloadList()directly at the end of the script, since the DOM will already be loaded.
- Ideally, use
- Test it out! Add items, refresh the page (or even close the tab, reopen it, etc.) and verify that your list is still there!
- If you still have the example items in your HTML, now is the time to remove or comment them out.
- Use the DevTools to inspect the
localStorageand see how your list is being saved. (Under the “Application” tab in Chrome/Edge, or the “Storage” tab in Firefox.)
Submission
Submit your three files (grocery.html, grocery-styles.css, and grocery-script.js) to Gradescope.