Joshua Wolfe
Joshua Wolfe

Reputation: 180

How do I save to local storage via vanilla JS

I can't seem to get local storage to work. The goal is to keep the todo list items on the page upon refresh. Every time I refresh the page it goes poof. The syntax seems right.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>TODO LIST</title>
    <link rel="stylesheet" href="./styles/style.css">
</head>
<body>
    <main id="main">
        <h1>THE TO-DO LIST:</h1>
        <form action="" id="add-task">
            <label for="todo">Add Task:</label>
            <input type="text" id="todo">
            <button>Add Task</button>
        </form> 
        <p class="center">To complete task, click on text.</p>            
        <ul id="task-list">
            <li class="task-complete">example_1 <button>Remove Task</button></li>           
        </ul>
    </main>
    <script src="./script/index.js"></script>
</body>
</html>
const form = document.querySelector('#add-task');
const input = document.querySelector('#todo');
const taskList = document.querySelector('#task-list');
let taskID = 0;

taskList.addEventListener('click', function(e) {
    if (e.target.tagName === 'BUTTON') {
        e.target.parentElement.remove();
        let inputTask = document.getElementById('todo');
        localStorage.setItem('email', inputTask.value);
    } else if (e.target.tagName === 'LI') {
        e.target.classList.toggle('task-complete');
    }
});

form.addEventListener('submit', function(e) {
    e.preventDefault();
    console.log(input.value);
    const newTask = document.createElement('li');
    const removeBtn = document.createElement('button');
    let savedInput = input.value;
    removeBtn.innerText = 'Remove Task';
    newTask.innerText = input.value;
    newTask.appendChild(removeBtn);
    taskList.appendChild(newTask);

    input.value = '';
    console.log(localStorage);
});
.task-complete {
    text-decoration: line-through;
}

Upvotes: 2

Views: 3046

Answers (3)

Mario
Mario

Reputation: 4988

You are not using de localStorage API, please take a look to this example. here I am using template to display the tasks. In the html file is the only change

<main id="main">
  <h1>THE TO-DO LIST:</h1>
  <form action="" id="add-task">
    <label for="todo">Add Task:</label>
    <input type="text" id="todo" />
    <button>Add Task</button>
  </form>
  <p class="center">To complete task, click on text.</p>
  <ul id="task-list">
    <li class="task-complete">example_1 <button>Remove Task</button></li>
  </ul>
</main>

<template id="task">
  <li class="task-complete">
    <span></span>
    <button>Remove task</button>
  </li>
</template>

In JavaScript I create a render function that will collect the task stored in localstorage. Populated when calling store(input.value) in the submit handler

const form = document.querySelector("#add-task");
const input = document.querySelector("#todo");
const taskList = document.querySelector("#task-list");
let taskID = 0;

taskList.addEventListener("click", function (e) {
  if (e.target.tagName === "BUTTON") {
    e.target.parentElement.remove();
    let inputTask = document.getElementById("todo");
    localStorage.setItem("email", inputTask.value);
  } else if (e.target.tagName === "LI") {
    e.target.classList.toggle("task-complete");
  }
});

form.addEventListener("submit", function (e) {
  e.preventDefault();
  console.log(input.value);
  const newTask = document.createElement("li");
  const removeBtn = document.createElement("button");
  let savedInput = input.value;
  removeBtn.innerText = "Remove Task";
  newTask.innerText = input.value;
  newTask.appendChild(removeBtn);
  taskList.appendChild(newTask);

  store(input.value);

  input.value = "";
  console.log(localStorage);
});

function getTasks() {
  return localStorage.tasks ? JSON.parse(localStorage.tasks) : [];
}

function store(task) {
  const tasks = getTasks();

  tasks.push(task);

  localStorage.setItem("tasks", JSON.stringify(tasks));
}

function render() {
  const tasks = getTasks();

  tasks.forEach((task) => {
    const newTask = createTask(task);

    taskList.appendChild(newTask);
  });
}

function createTask(task) {
  const template = document.querySelector("#task");
  const taskNode = template.content.cloneNode(true);

  taskNode.querySelector("span").innerText = task;

  return taskNode;
}

render();

The render function run every first render of the page, so tasks list will be populated

Upvotes: 1

renatodeleao
renatodeleao

Reputation: 92

Joshua, here are a few things from looking at your sample:

  • First, you're setting the localStorage to a single item, with the current input value, not a collection of tasks like an array
  • It also seems that you're not getting the saved data on page reload, that's why nothing happens when page reloads
  • Remember that you can only save strings to localStorage, in a todo list you might want to save an array (a collection of todos), but since you can't do it you need to convert it to a string while saving (JSON.stringify(yourArray) will help you with that), and parse it back to an Array when loading (JSON.parse)
const form = document.querySelector('#add-task');
const input = document.querySelector('#todo');
const taskList = document.querySelector('#task-list');
let taskID = 0;
let tasks = [] // here will hold your current todos collection

// a function that will retrieve the saved todos from local storage
//
// note that 'tasks' can be any string identifier that you want — 'todos'
// would also work — but you need to use the same for localStorage.getItem 
// and localStorage.setItem
function getTasksFromLocalStorage(){
  // it will return `null` if nothing's there
  tasks = localStorage.getItem('tasks') || []

  if (tasks) {
    // convert it to an array so you can loop over it
    tasks = JSON.parse(tasks)
  }
}

function addTask(text) {
   // CREATE DOM ELEMENTS
   const newTask = document.createElement('li');
   const removeBtn = document.createElement('button');

   removeBtn.innerText = 'Remove Task';
   // set the text to the provided value
   newTask.innerText = text;

   // append the remove button
   newTask.appendChild(removeBtn);

   // append it to the dom so we can see it
   taskList.appendChild(newTask)
}

// on page load get tasks from local storage
// then loop over it, create the DOM elements and append them to 
// the taskList
document.addEventListener('DOMContentLoaded', function() {
   getTasksFromLocalStorage()

   // if we have saved tasks, loop over them and render to the dom
   tasks.forEach(function(savedTaskText) {
     addTask(savedTaskText)
   })

})

// then on your code, you need to update to push 
// the current inputed `task` to the `tasks` collection (Array)
// then save the entire collection to the local storage
// then add the new task to the DOM
// and finally reset the input
form.addEventListener('submit', function(e) {
    e.preventDefault();
    console.log(input.value);

    // save it to the current holding list
    tasks.push(input.value)

    // save a copy of the updated list to the localStorage, so when you
    // reload the page you get saved items!
    localStorage.setItem('tasks', tasks)

    // add it to DOM
    addTask(input.value);

    // reset the input
    input.value = '';
});

There's more things you need to do, if you want tasks to have unique ids (since, so you can remove them later), but the code was simplified for brevity of explanation (and yet you got a long answer anyways).

Here's so docs and suggested reading:

Good luck and Happy coding ✌️

Upvotes: 3

Kaashan
Kaashan

Reputation: 382

There are 2 problems with your code.

First, you are not saving each to-do task entered by user upon form submit. If you want to save each to-do task entered by user in localStorage, then modify the form submit handler as below:

form.addEventListener('submit', function(e) {
            e.preventDefault();
            const newTask = document.createElement('li');
            const removeBtn = document.createElement('button');
            let savedInput = input.value;
            removeBtn.innerText = 'Remove Task';
            newTask.innerText = input.value;
            newTask.appendChild(removeBtn);
            taskList.appendChild(newTask);
            localStorage.setItem('Task'+taskID, input.value);
            taskID++;
            input.value = '';
        });

Second, you are not utilizing the previously saved data in localStorage to show the list of to-dos that were entered by user before the page was loaded. You can achieve that by using below function code:

function showSavedToDos() {
            const keys = Object.keys(localStorage);
            let i = keys.length;

            while (i--) {
                const newTask = document.createElement('li');
                const removeBtn = document.createElement('button');
                removeBtn.innerText = 'Remove Task';
                newTask.innerText = localStorage.getItem(keys[i]);
                newTask.appendChild(removeBtn);
                taskList.appendChild(newTask);
            }
        }
        showSavedToDos();

Upvotes: 2

Related Questions