Skip to content

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

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.

form with category dropdown

  1. In grocery.html, add a drop-down menu to the form (don’t forget a label!). Give it the id categorySelect and the name category. It should have the six following options:
    • Produce
    • Dairy
    • Poultry
    • Meat
    • Pantry
    • Other
  2. Add a new column header to the table for “Category”.
    • Don’t forget to add the scope attribute 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)
  3. In grocery-script.js, update the addItemToList() function to get the category input and its value.
  4. In makeRow(), create a new cell for the category and append it to the row.
  5. 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.
  6. 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:

fully styled form

  1. First, in grocery-styles.css, let’s modify the rules for form-container:
    • Set its width to fit-content so that it wraps tightly around the form.
    • Also give it 5px of vertical padding and 10px of horizontal padding.
  2. 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.

  3. 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 300px so 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.
  4. Style the submit button to look like the “Click” button in Figure 5.31 from the textbook.

  5. 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.
  6. 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:

localStorage view in Chrome/Edge DevTools

(Note: the above image is from Chrome/Edge DevTools. Firefox uses a “Storage” tab instead of “Application”.)

  1. In grocery-script.js, implement the appendToSavedList() 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 localStorage as a string with the key "items".
    • Remember: everything in localStorage is stored as a string!
      • We use JSON.stringify(...) and JSON.parse(...) to convert between strings and arrays/objects.
    • Write code to perform each of the tasks outlined by the TODO comments.
  2. At the end of the addItemToList() function, call appendToSavedList() with the appropriate arguments to save the new item to localStorage.
  3. 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.
  4. Finally, we need to call loadList() once the page loads. Two ways to do this:
    • Ideally, use document.addEventListener(...) to listen for the DOMContentLoaded event and specify a callback function.
    • Alternatively, because this script is at the end of <body>, we could also just call loadList() directly at the end of the script, since the DOM will already be loaded.
  5. 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 localStorage and 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.