Nitish Dayal, Software & Applications Developer - Contact
Last Commit Date: May 12, 2017
The web page simulates a restaurant's menu. The user should be able to
add new dishes to the list using the form
HTML element without having
to refresh the page. Currently, when the user submits a dish into the form,
the page reloads (as this is the default action of a submit
event)
and the list remains empty. Write the necessary JavaScript code to bring
functionality to the page.
In the script
tag, we're provided 3 const
variables: one referencing
the form
element (addItems
), one referencing the unordered list
element (itemsList
), and an empty array (items
). This one is lengthy,
so let's get started with the necessary steps:
Steps:
-
Attach an event handler to the
form
element that will listen for the 'submit' event and call upon an event handler (to be defined, for now simply provide the name that you'll give to the function).addItems.addEventListener('submit', addItem)
-
Define the event handler as a function which accepts an
event
as a parameter and will prevent the default behavior of that event:
const addItem = (e) => {
e.preventDefault()
}
- In the function body, declare a
const
and define it as the value of theinput
element and declare anotherconst
as an object with the properties 'text' (set to theinput
value) and 'done' (set to theboolean
value false):
/* In function body */
const text = (e.target.querySelector('[name="item"]').value(),
item = {
text,
done: false
}
- Push the newly created
item
object into theitems
array & store theitems
array in localStorage. Values saved in localStorage are associated with akey
and can only be String values, so we'll convert theitems
array into a JSON string. Reset the form:
/* In function body */
items.push(item)
localStorage.setItem('dishes', JSON.stringify(items))
e.target.reset()
- NOTE: Submit some values into the form.In your browser's dev tools,
navigate to the
Application
tab and open up 'Local Storage > file://'. You should see these items stored under the key 'dishes' as a string representation of theitems
array.
- Declare a function that will be responsible for generating the necessary
HTML to display each item in the
items
array as a list item with a clickable checkbox.
const populateList = (items, itemsList) => {
// If the parameter `items` isn't an array, go no further
if (!(items instanceof Array)) return false
// Update the 'itemsList' HTML to contain each item stored in the `items` array
itemsList.innerHTML = items.map((item, i) => {
return `
<li>
<input type="checkbox" data-index=${i} id="item${i}" ${item.done ? 'checked' : ''} />
<label for="item${i}">${item.text}</label>
</li>
`
}).join('')
}
- Go back to the event handler function body and call the newly defined function after
we've pushed an item object into the
items
array:
/* Right after 'items.push(item)' */
populateList(items, itemsList)
- At the very top of your JavaScript code, change
const items
so that it is either an array generated from parsing through the items currently in localStorage, or if there is nothing in localStorage, an empty array.
const addItems = document.querySelector('.add-items'),
itemsList = document.querySelector('.plates'),
items = JSON.parse(localStorage.getItem('dishes')) || []; // This is the line we're changing
- We need to call the
populateList
method as soon as the document loads so that we can generate the menu items if there is something in the localStorage:
document.onload = populateList(items, itemsList)
- Currently, the 'done' property of each item element is never updated, so the status
of the checkbox does not carry across page reloads. Attach an event handler to the
itemsList
that will call an event handler function on each 'click' event.
itemsList.addEventListener('click', toggleDone)
- Define this event handler function so that it accepts an event as a parameter and,
if the target of the event contains the text 'input' anywhere, we'll toggle
the
done
value of correct object in theitems
array and update the localStorage to reflect that change:
const toggleDone = (e) => {
if (!e.target.matches('input')) return;
const element = e.target,
idx = element.dataset.index;
items[idx].done = !items[idx].done
localStorage.setItem('dishes', JSON.stringify(items))
}
Guess what, friends? We're already HALF WAY THEREEEEEEEE!!!!