Using localStorage and JSON within Webpack

4 hours ago 3
ARTICLE AD BOX

I am working on a ToDo list app and I am having a little difficulty with local storage and JSON. I am using webpack and I have three modules:

index.js - which is my entry-point template.js - which is another bundle where I have just an object responsible for creating the todo-list items mydomMethods.js - where I have all the function and DOM manipulations

I was able to set up the localStorage and JSON in one of the functions in the mydomMethods that takes the input from the input fields and use the input values to create the list when a button is clicked. When I check in the console, I see that the object is there.

However, with my current setup, I can't seem to get how to use localStorage.getItem() to get the items and display them on the page even when I refresh the page.

index.js:

import "./styles.css"; import { newTask } from "./mydomMethods.js"; import { cancelTask } from "./mydomMethods.js"; import { addTaskFromPageButton } from "./mydomMethods.js"; import { addTaskSideBar } from "./mydomMethods.js"; import { myTodoList } from "./mydomMethods.js"; import { displayList } from "./mydomMethods.js"; displayList(myTodoList); const addTaskButton = document.querySelector("#add-task"); addTaskButton.addEventListener('click', newTask()); const addButton = document.querySelector('#add-btn'); addButton.addEventListener('click', addTaskSideBar); const secondTaskBtn = document.querySelector('.add-task-button'); secondTaskBtn.addEventListener('click', addTaskFromPageButton); const cancelButton = document.getElementById('cancel-task'); cancelButton.addEventListener('click', cancelTask);

template.js:

export class Todo { constructor(title, description, dueDate, priority) { this.title = title; this.description = description; this.dueDate = dueDate; this.priority = priority; } };

mydomMethods.js:

import { Todo } from "./template.js"; export const myTodoList = JSON.parse(localStorage.getItem("displayList")) || []; displayList(myTodoList); export function displayList(listing) { const list = document.querySelector('.task-list'); list.textContent = ""; for(const task of listing) { const checkBox = Object.assign(document.createElement('input'), { type: 'checkbox', id: 'check-box', name: 'check-box' }); const itemTitle = document.createElement('li'); const titleHolder = document.createElement('div'); titleHolder.id = 'title-holder'; titleHolder.append(checkBox, itemTitle); const itemDescription = document.createElement('li'); const dueTime = document.createElement('li'); const separator = document.createElement('div'); separator.id = 'separator'; itemTitle.textContent = `${task.title}`; itemDescription.textContent = `${task.description}`; dueTime.textContent = `${task.dueDate}`; list.append(titleHolder, itemDescription, dueTime, separator); }; }; export function newTask() { const titleInput = document.querySelector('#title-input'); const descriptionInput = document.querySelector('#description-input'); const closeButton = document.querySelector("#add-task"); closeButton.addEventListener('click', ()=> { const form = document.getElementById('task-form'); const title = titleInput.value; const description = descriptionInput.value; const todo = new Todo(title, description, 'monday', 'very Important'); myTodoList.push(todo); localStorage.setItem("TodoList", JSON.stringify(myTodoList)); displayList(myTodoList); form.reset(); console.log(myTodoList); dialog.close(); }); }; export function cancelTask() { const dialog = document.getElementById('dialog'); const taskList = document.querySelector('.task-list'); const newTaskArea = document.querySelector('.new-task'); if(taskList.textContent === "") { newTaskArea.style.display = ""; dialog.close(); } else { displayList(myTodoList); dialog.close(); }; }; export function addTaskFromPageButton() { const dialog = document.getElementById('dialog'); const container = document.querySelector('.new-task'); container.style.display = 'none'; dialog.showModal(); }; export function addTaskSideBar() { const dialog = document.getElementById('dialog'); const container = document.querySelector('.new-task'); container.style.display = 'none'; dialog.showModal(); };

The CSS:

body { box-sizing: border-box; display: grid; grid-template-columns: 300px 1fr; margin: 0 auto; } aside { min-height: 100vh; background-color: rgb(202, 202, 202); padding-left: 15px; } main { display: grid; grid-template-rows: repeat(3, 1fr); } .projects { padding-left: 10px; font-size: 1.5rem; } #dialog { max-width: 600px; min-height: 200px; border-radius: 10px; border: solid 2px aliceblue; box-shadow: 1px 3px 20px 5px rgba(57, 53, 53, 0.5); text-align: center; position: fixed; bottom: 650px; left: 250px; } .dialog-container { display: flex; flex-direction: column; gap: 25px; } .options-icon { display: flex; border: 1px solid grey; border-radius: 8px; padding: 2px; } .options-icon > button { border: none; background: none; font-weight: bold; font-size: 0.95rem; color: rgb(93, 92, 92); } .options-container { display: flex; gap: 35px; justify-content: center; align-items: center; } #cancel-task { font-size: 0.95rem; font-weight: bold; border: none; padding: 5px 10px; border-radius: 5px; background-color: rgb(104, 102, 102); color: white; } #add-task { width: 100px; align-self: end; background-color: rgb(210, 85, 85); font-size: 0.95rem; font-weight: bold; color: white; padding: 5px; border: none; border-radius: 5px; } .header-icon, .icons > div { /* padding: 5px; */ display: flex; align-items: center; padding: 10px; gap: 10px; } .icons > div:hover { background-color: rgb(165, 165, 165); padding: 5px; } a { text-decoration: none; color: black } #check-box { width: 1.5rem; height: 1.5rem; border-radius: 50%; background-color: white; border-radius: 50%; border: 1px solid #ddd; } #title-holder { display: flex; align-items: center; } li { list-style: none; } #separator { max-width: 566px; border: 1px solid grey; margin-top: 5px; margin-bottom: 5px; } .new-task { text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; } .new-task > p{ width: 250px; } .buttons-holder { display: flex; gap: 10px; justify-content: end; align-items: b; padding-right: 5px; } .new-task > button { background-color: rgb(232, 71, 71); color: white; border-radius: 5px; padding: 5px; border: white; } form { display: flex; flex-direction: column; gap: 5px; } #description-input { width: 500px; height: 25px; border: none; outline: none; font-size: 1rem; } #title-input { width: 500px; height: 50px; border: none; outline: none; font-size: 1.7rem; font-weight: bold; } #options-container { display: flex; justify-content: center; gap: 20px; padding: 10px; } #options-container > div { border: 1px white solid; padding: 5px; } #input-container { display: flex; flex-direction: column; } .icon-button { border: none; background: none; font-size: 1rem; font-weight: bold; width: 100%; text-align: left; }

The HTML:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Todo App</title> </head> <body id="body"> <aside> <nav> <div class="header-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="25" width="25"><title>circle-outline</title><path d="M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg> <h3>Jasinski</h3> </div> <div class="icons"> <div> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="25" width="25"><title>plus-circle</title><path d="M17,13H13V17H11V13H7V11H11V7H13V11H17M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" /></svg> <button class="icon-button" id="add-btn">Add Task</button> </div> <div> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="25" width="25"><title>magnify</title><path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" /></svg> <button class="icon-button">Search</button> </div> <div> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="25" width="25"><title>inbox-arrow-down</title><path d="M16,10H14V7H10V10H8L12,14M19,15H15A3,3 0 0,1 12,18A3,3 0 0,1 9,15H5V5H19M19,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3Z" /></svg> <button class="icon-button">Inbox</button> </div> <div> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="25" width="25"><title>calendar-blank</title><path d="M19,19H5V8H19M16,1V3H8V1H6V3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3H18V1" /></svg> <button class="icon-button">Today</button> </div> <div> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="25" width="25"><title>calendar-month</title><path d="M9,10V12H7V10H9M13,10V12H11V10H13M17,10V12H15V10H17M19,3A2,2 0 0,1 21,5V19A2,2 0 0,1 19,21H5C3.89,21 3,20.1 3,19V5A2,2 0 0,1 5,3H6V1H8V3H16V1H18V3H19M19,19V8H5V19H19M9,14V16H7V14H9M13,14V16H11V14H13M17,14V16H15V14H17Z" /></svg> <button class="icon-button">Upcoming</button> </div> <div> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="25" width="25"><title>chart-areaspline</title><path d="M17.45,15.18L22,7.31V19L22,21H2V3H4V15.54L9.5,6L16,9.78L20.24,2.45L21.97,3.45L16.74,12.5L10.23,8.75L4.31,19H6.57L10.96,11.44L17.45,15.18Z" /></svg> <button class="icon-button">Reporting</button> </div> </div> <div> <div> <h3 class="projects">My Projects</h3> </div> </div> </nav> </aside> <main> <dialog id="dialog"> <div class="dialog-container"> <form action="post" id="task-form"> <input type="text" id="title-input" placeholder="Name Your Task" name="task-title"> <input type="text" id="description-input" placeholder="Describe Your Task" name="task-descriptioin"> </form> <div class="options-container"> <div class="options-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="20" width="20"><title>calendar-range</title><path d="M9,10H7V12H9V10M13,10H11V12H13V10M17,10H15V12H17V10M19,3H18V1H16V3H8V1H6V3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M19,19H5V8H19V19Z" /></svg> <button class="date-button">Date</button> </div> <div class="options-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="20" width="20"><title>paperclip</title><path d="M17,7V17.5C17,20.54 14.54,23 11.5,23C8.46,23 6,20.54 6,17.5V6C6,3.79 7.79,2 10,2C12.21,2 14,3.79 14,6V16.5C14,17.88 12.88,19 11.5,19C10.12,19 9,17.88 9,16.5V7H10V16.5C10,17.33 10.67,18 11.5,18C12.33,18 13,17.33 13,16.5V7.15L13,7V6C13,4.34 11.66,3 10,3C8.34,3 7,4.34 7,6V16.44L7,17.5C7,20 9,22 11.5,22C14,22 16,20 16,17.5V7H17Z" /></svg> <button>Attachment</button> </div> <div class="options-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="20" width="20"><title>flag</title><path d="M14.4,6L14,4H5V21H7V14H12.6L13,16H20V6H14.4Z" /></svg> <button>Priority</button> </div> <div class="options-icon"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="20" width="20"><title>alarm-note</title><path d="M17.4,1.86L16.11,3.39L20.71,7.25L22,5.72L17.4,1.86M6.6,1.86L2,5.71L3.29,7.24L7.88,3.39L6.6,1.86M12,4A9,9 0 0,0 3,13A9,9 0 0,0 12,22C12.33,22 12.67,22 13,21.94V19.94C12.67,20 12.33,20 12,20A7,7 0 0,1 5,13A7,7 0 0,1 12,6C15.1,6 17.83,8.03 18.71,11H20.78C19.85,6.9 16.2,4 12,4M23,15H20V20.5A2.5,2.5 0 0,1 17.5,23A2.5,2.5 0 0,1 15,20.5A2.5,2.5 0 0,1 17.5,18C18.04,18 18.57,18.18 19,18.5V13H23V15M11.5,8V13.25L7.5,15.62L8.25,16.85L13,14V8H11.5Z" /></svg> <button>Reminder</button> </div> </div> <div class="buttons-holder"> <button id="cancel-task">Cancel</button> <button id="add-task">Add Task</button> </div> </div> </dialog> <div class="content-container"> <ul class="task-list"></ul> </div> <div class="new-task"> <h4>Capture now, plan later</h4> <p>Here is your go-to spot for quick task entry. Clear your mind now, organize when you're ready.</p> <button class="add-task-button">+ Add Task</button> </div> <div> </div> </main> </body> </html>
Read Entire Article