Joe Consterdine
Joe Consterdine

Reputation: 1053

Best way to use Local Storage in this example?

I've built a to do list in vanilla JS, but now I want to convert it to local storage.

I know how to use set, get and remove in local storage, but I'm not sure how to use it on my app.

because each to do item has text, a delete button, edit button, checkbox etc I'm not sure how I save that.

Or can I save just the text and somehow render it with the other elements?

Just wanting to get an idea of the theory/best way to think about taking this task on.

I'm wondering if there's a simple way to do it or it's more a case of completely restructuring the way the app works.

Cheers

JS

// To do list

// Cache DOM
var addToDo = document.getElementById('add-to-do');
var taskHolder = document.getElementById('task-holder');
var uncompleteTasks = document.getElementById('uncompleted-tasks');
var completedTasks = document.getElementById('completed-tasks');

// Bind events
var bindEvents = function(listItem, checkboxEventHandler) {
  // Delete
  var deleteToDo = listItem.querySelector('.delete-to-do');
  deleteToDo.addEventListener('click', deleteTask);
  // Edit
  listItem.querySelector('.edit-to-do').addEventListener('click', editTask);
  listItem.querySelector('.edit-holder').addEventListener('keyup', editTaskEnter);
  // Checkbox
  var checkbox = listItem.querySelector('input.edit-to-do');
  checkbox.onchange = checkboxEventHandler;
}

// Create list item
var createListItem = function() {
  var listItem = document.createElement('li');
  var deleteToDo = document.createElement('button');
  deleteToDo.innerHTML = 'delete';
  deleteToDo.classList.add('delete-to-do');
  var editToDo = document.createElement('button');
  editToDo.innerHTML = 'edit';
  editToDo.classList.add('edit-to-do');
  var toDoStatus = document.createElement('input');
  toDoStatus.type = 'checkbox';
  toDoStatus.classList.add('edit-to-do');
  var editHolder = document.createElement('input');
  editHolder.type = 'text';
  editHolder.classList.add('edit-holder');

  listItem.appendChild(deleteToDo);
  listItem.appendChild(editToDo);
  listItem.appendChild(toDoStatus);
  listItem.appendChild(editHolder);

  return listItem;
}

// Add task
var addTask = function(e) {
  var taskHolderValue = taskHolder.value;
  if(taskHolderValue) {
    var taskHolderElement = document.createElement('label');
    taskHolderElement.classList.add('to-do-item');
    taskHolderElement.innerHTML = taskHolderValue;
    var listItem = createListItem();
    listItem.insertBefore(taskHolderElement, listItem.childNodes[0]);
    uncompleteTasks.appendChild(listItem);
    bindEvents(listItem, taskCompleted);

    taskHolder.value = '';
  } else {
    alert("You didn't add a to a to do!");
  }
}

var addTaskEnter = function(e) {
  var key = 'which' in e ? e.which : e.keyCode;
  if(key === 13) {
    addTask();
  }
}

// Delete task
var deleteTask = function() {
  var listItem = this.parentNode;
  console.log(listItem);
  var parentItem = listItem.parentNode;
  parentItem.removeChild(listItem);
}

// Edit task
var editTask = function() {
  var defaultValue = this.parentNode.querySelector('label').innerHTML;
  var listItem = this.parentNode;
  var listParent = this.parentNode;
  var editedValue = listParent.querySelector('input.edit-holder').value;
  if(listItem.classList.contains('editing') && editedValue) {
    listParent.querySelector('label').innerHTML = editedValue;
  }
  listItem.classList.toggle('editing');
}

// Edit task enter
var editTaskEnter = function(e) {
  var key = 'which' in e ? e.which : e.keyCode;
  if(key === 13) {
    editTask.call(this);
  }
}

// Task completed
var taskCompleted = function() {
  var listItem = this.parentNode;
  completedTasks.appendChild(listItem);
  this.parentNode.classList.add('completed');
  bindEvents(listItem, taskUncompleted);
}

// Task uncompleted
var taskUncompleted = function() {
  var listItem = this.parentNode;
  uncompleteTasks.appendChild(listItem);
  this.parentNode.classList.remove('completed');
  bindEvents(listItem, taskCompleted);
}

// Add task
addToDo.addEventListener("click", addTask);
taskHolder.addEventListener("keyup", addTaskEnter);

// Loop over uncomplete tasks
for(i=0; i<completedTasks.length; i++) {
  var listItem = completedTasks[i];
  uncompleteTasks.appendChild(listItem);
  bindEvents(listItem, completedTasks);
}

Upvotes: 0

Views: 97

Answers (1)

Khauri
Khauri

Reputation: 3863

You don't really need to save any of the html, but you can save things associated with it. It's all in the way you store your todo list. Consider creating some kind of variable you can use to store your todo list items such as an array or object.

A common method is to use an array of objects. This is beneficial because you can also put extra details in it. Something like this:

var todos = [ { id: 1, text : "Clean", completed : true}, { id : 2, text : "Eat", completed : false } ... ]

In this example I've put an id so that I could potentially use it later to reference a specific item, but this isn't strictly necessary.

Using JSON#parse and JSON#stringify you can convert this array to and from a string so that it can be stored in localStorage.

Whenever the page loads you should populate that todo list and whenever the todo list changes you should save the changes back to localStorage.

Lastly you should modify your code to iterate through the array each time the user adds or removes a todo list item, possibly using Array#splice to remove the item and Array#push to append a new one to the end, then recreate your entire todo list section.

Upvotes: 1

Related Questions