Day15 of #100DaysOfCode

Kushagra Kesav
3 min readFeb 22, 2022

--

#CodeTogether Day 15/100

Hii folks 🙌

Today I have completed the 15th video of JavaScript30!

Project 15: LocalStorage and Event Delegation

Source: https://javascript30.com

Learnings:

The JS was given to us

const addItems = document.querySelector(".add-items");
const itemsList = document.querySelector(".plates");
const items = [];

We have handles to the form where the user inputs new items and the list where the items are displayed. The items array holds all the items.

The main steps involved completing our app

  • Add new items to the items array
  • Display the items in the items array
  • Toggle an item
  • Save the list to local storage

Adding new items

We add new items using an HTML form. Submitting a form by default makes a get request and goes to the new URL. We call e.preventDefault() to prevent the default behavior.

function addItem(e) {
e.preventDefault();
const text = (this.querySelector('[name=item]')).value;
const item = {
text,
done: false
};
items.push(item); // display the list - populateList();
// store to local storage - localStorage.set()
this.reset();
}
addItems.addEventListener('submit', addItem);

In addItem(), this refers to the form.add-items DOM object. We then select the text input element and get the text inside of it. We create a new items object and then push it into the items list. Once it is added we call reset() on the form to clear the input text box.

Display the items

populateList() does the work of taking in an array and displaying the list. We could have populateList() just use the global items and itemsList variables, but that would be hardcoding, it's better to pass the variables in case we ever want to use the functions for anything else.

function populateList(plates = [], platesList) {
platesList.innerHTML = plates.map((plate, i) => {
return `
<li>
<input type="checkbox" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
<label for="item${i}">${plate.text}</label>
</li>
`;
}).join('');
}
function addItem(e){
//...
// display the list - populateList()
populateList(items, itemsList)
}

populateList() uses template strings and [].map to create <li> elements from each element in the array, which is late concatenated into one string which platesList.innerHTML is set to. addItem uses populateList to render all the current items.

Toggle an item

toggleDone deals with the click event to toggle an item. We can attach a listener on the checkbox element, but the moment we add a new item, all <li> elements are recreated by populateList. Hence adding an event listener on those items makes no sense. We solve this issue by using event delegation - we let the parent element take care of the click event to toggle an item. The parent in this case is the ul.item-plates element.

function toggleDone(e) {
if (!e.target.matches('input')) return; // skip this unless it's an input
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
populateList(items, itemsList);
}
itemsList.addEventListener('click', toggleDone);

If you had paid close attention to the populateList function you'd see that the input element for the item has data-index=${i} where i is the index of that item in the items array. So now toggleDone checks if the event target is an input element (only input element being a checkbox), extracts the index from the data attribute, toggles the done in the items array, and then re-renders the list by calling populateList.

Save the list to LocalStorage

We want to persist the list after a refresh or for a later point in time, for this we’ll use local storage. Local storage is a key-value store where the key and value are strings.

A simple example

// set the value "Tom" for key "myCat" in the local storage
localStorage.setItem('myCat', 'Tom');
// cat has value "Tom"
var cat = localStorage.getItem('myCat');
//remove the "myCat" key from local storage
localStorage.removeItem('myCat');

You can learn more about Local Storage @ MDN Docs.

Since we want to keep the local storage in sync with the UI, we’ll update the local storage whenever we call populateList().

function toggleDone(e) {
//...
localStorage.setItem('items', JSON.stringify(items));
populateList(items, itemsList);
}
function addItem(e) {
//...
localStorage.setItem('items', JSON.stringify(items));
populateList(items, itemsList);
//...
}

Also, we need to get the items from local storage when we load the page. We’ll modify items array to take read from the local storage first, if it doesn't have an 'items' key, we'll assign it to an empty array as we had earlier.

const items = JSON.parse(localStorage.getItem('items')) || [];

Today I learned (T-I-L):

  • About Local Storage of Browser
  • Event Delegation

That is all for Day15 ✅

Thanks for reading, See you tomorrow!

--

--