Oscar
Oscar

Reputation: 135

Update localStorage value (todo list)

I am doing a task list with an editable function for the each task item. What I expect is that when I update item's value, the value in LocalStorage update simultaneously. Currently, the value in LocalStorage can be updated, however, it only updates the last value of it no matter which item's value I modify. And the one should be changed does not be modified. How do I change correct localStorage value when I revise the task item?

const todo__input = document.querySelector(".todo__input")
const add__btn = document.querySelector(".add__btn")
const item__sector = document.querySelector(".item__sector")

function createToDoItem(toDoItem) {
  const position = "beforeend"
  const item = `
    <div class="item">
      <input type="checkbox" class="done__btn">
      <input type="text" class="item__content" value="${toDoItem}" disabled>
      <button class="edit__btn"><i class="far fa-edit"></i></button>
      <button class="delete__btn"><i class="far fa-trash-alt"></i></button>
    </div>
  `
  item__sector.insertAdjacentHTML(position, item)
  return item__sector
}

// load todo item from localstorage when page is loaded
document.addEventListener("DOMContentLoaded", getLocalStorage)

// add item to the item sector
add__btn.addEventListener("click", e => {
  e.preventDefault()
  const input__value = todo__input.value
  if (input__value.trim() === "") { return }
  createToDoItem(input__value)
  saveLocalStorage(input__value)
  todo__input.value = ""
})

// keypress Enter
document.addEventListener("keypress", e => {
  if (e.keyCode == 13) {
    e.preventDefault()
    const input__value = todo__input.value
    if (input__value.trim() === "") { return }
    createToDoItem(input__value)
    saveLocalStorage(input__value)
    todo__input.value = ""
  }
})


// the function on item (done, edit, and delete)
item__sector.addEventListener("click", e => {
  const parent = e.target.parentElement

  // done
  if (e.target.classList.contains("done__btn")) {
    e.target.nextElementSibling.classList.toggle("done__color")
  }
  // edit the todo item 
  if (e.target.classList.contains("edit__btn")) {
    if (e.target.previousElementSibling.disabled.disabled == true) {
      e.target.previousElementSibling.disabled = !e.target.previousElementSibling.disabled

    } else {
      e.target.previousElementSibling.disabled = !e.target.previousElementSibling.disabled
      e.target.previousElementSibling.setAttribute("value", e.target.previousElementSibling.value)
      editLocalStorage(e.target.previousElementSibling)
    }
  }
  // delete todo item
  if (e.target.classList.contains("delete__btn")) {
    parent.remove()
    deleteLocalStorage(e.target.previousElementSibling.previousElementSibling)
  }
})

// function for check todo status in the LocalStorage
function checkLocalStorage() {
  let todos
  if (localStorage.getItem("todos") === null) {
    todos = []
  } else {
    todos = JSON.parse(localStorage.getItem("todos"))
  }
  return todos
}

// function for save localstorage
function saveLocalStorage(todo) {
  const todos = checkLocalStorage()
  todos.push(todo)
  localStorage.setItem("todos", JSON.stringify(todos))
}

// function for get item and render to the screen from localstorage
function getLocalStorage() {
  const todos = checkLocalStorage()
  todos.forEach(todo => {
    createToDoItem(todo)
  })
}

// edit localStorage 

function editLocalStorage(todo) {
  const todos = checkLocalStorage()
  const todoIndex = todo.getAttribute("value")
  todos.splice(todos.indexOf(todoIndex), 1, todoIndex)
  localStorage.setItem("todos", JSON.stringify(todos))
}

====

<body>
  <div class="container">
    <h1 class="title">My To-Do List</h1>
    <form class="add__todo">
      <input type="text" class="todo__input" placeholder="Add a task...">
      <button class="add__btn">Add</button>
    </form>
    <div class="item__sector">

    </div>
    <div class="item__status">
      <button class="all">All</button>
      <button class="completed">COMPLETE</button>
      <button class="incompleted">UNCOMPLETE</button>
    </div>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
  <script src="app.js"></script>
</body>

Upvotes: 1

Views: 403

Answers (1)

George Tibetegya
George Tibetegya

Reputation: 126

The reason that causes your solution to edit the last value is:-

The todoIndex variable inside the editLocalStorage function is referencing the new updated value from your input which is not yet stored inside the todos array in local storage therefore indexOf() returns -1 hence editing the last value.

I have rewritten the JS with a tweak to the functions item__sector.addEventListener, editLocalStorage and added a global variable edit__index

Code Snippet

const todo__input = document.querySelector(".todo__input")
const add__btn = document.querySelector(".add__btn")
const item__sector = document.querySelector(".item__sector")
let edit__index = -1

function createToDoItem(toDoItem) {
  const position = "beforeend"
  const item = `
    <div class="item">
      <input type="checkbox" class="done__btn">
      <input type="text" class="item__content" value="${toDoItem}" disabled>
      <button class="edit__btn"><i class="far fa-edit"></i></button>
      <button class="delete__btn"><i class="far fa-trash-alt"></i></button>
    </div>
  `
  item__sector.insertAdjacentHTML(position, item)
  return item__sector
}

// load todo item from localstorage when page is loaded
document.addEventListener("DOMContentLoaded", getLocalStorage)

// add item to the item sector
add__btn.addEventListener("click", e => {
  e.preventDefault()
  const input__value = todo__input.value
  if (input__value.trim() === "") { return }
  createToDoItem(input__value)
  saveLocalStorage(input__value)
  todo__input.value = ""
})

// keypress Enter
document.addEventListener("keypress", e => {
  if (e.keyCode == 13) {
    e.preventDefault()
    const input__value = todo__input.value
    if (input__value.trim() === "") { return }
    createToDoItem(input__value)
    saveLocalStorage(input__value)
    todo__input.value = ""
  }
})


// the function on item (done, edit, and delete)
item__sector.addEventListener("click", e => {
  const parent = e.target.parentElement
  // done
  if (e.target.classList.contains("done__btn")) {
    e.target.nextElementSibling.classList.toggle("done__color")
  }
  // edit the todo item s
  if (e.target.classList.contains("edit__btn")) {
    if (e.target.previousElementSibling.disabled.disabled == true) {
      e.target.previousElementSibling.disabled = !e.target.previousElementSibling.disabled
    } else {
      const todos = checkLocalStorage()
      if (edit__index === -1) {
        const valueBeforeEdit = e.target.previousElementSibling.getAttribute("value")
        edit__index = todos.indexOf(valueBeforeEdit)
      } else {
        const valueAfterEdit = e.target.previousElementSibling.value
        editLocalStorage(edit__index, valueAfterEdit)
        edit__index = -1
      }
      e.target.previousElementSibling.disabled = !e.target.previousElementSibling.disabled
      e.target.previousElementSibling.setAttribute("value", e.target.previousElementSibling.value)

    }
  }
  // delete todo item
  if (e.target.classList.contains("delete__btn")) {
    parent.remove()
    deleteLocalStorage(e.target.previousElementSibling.previousElementSibling)
  }
})

// function for check todo status in the LocalStorage
function checkLocalStorage() {
  let todos
  if (localStorage.getItem("todos") === null) {
    todos = []
  } else {
    todos = JSON.parse(localStorage.getItem("todos"))
  }
  return todos
}

// function for save localstorage
function saveLocalStorage(todo) {
  const todos = checkLocalStorage()
  todos.push(todo)
  localStorage.setItem("todos", JSON.stringify(todos))
}

// function for get item and render to the screen from localstorage
function getLocalStorage() {
  const todos = checkLocalStorage()
  todos.forEach(todo => {
    createToDoItem(todo)
  })
}

// edit localStorage 

function editLocalStorage(editIndex, editValue) {
  const todos = checkLocalStorage()
  todos.splice(editIndex, 1, editValue)
  localStorage.setItem("todos", JSON.stringify(todos))
  debugger
}

Note: There is an edge case of having more than one todo item with the same value that you need to solve for.

Upvotes: 2

Related Questions