Local storage - wrong list items appear on refresh

136 views Asked by At

I've created a to-do list with local storage. If you create three list items and delete the second one, the deleted list item will reappear in place of the third item on refresh.

Edit: I'm not sure whether it's to do with local storage or with the original todo array. In the code below, I'm trying to remove the relevant value from the array, but I suspect this isn't working (logging the array to the console produces no result).

Although it has nothing to do with local storage, I think the issue lies with the following code:

function removeItem() {
  let item = this.parentNode.parentNode;
  let parent = item.parentNode;
  let id = parent.id;
  console.log(id)
  let value = parent.textContent;
     todo.splice(todo.indexOf(value, 1));
  this.parentNode.parentNode.removeChild(this.parentNode);    
  saveTodos();
}

Edit: Here is the code I used to store the list items:

function saveTodos() {
  let jsonstr = JSON.stringify(todo);
  localStorage.setItem('todo', jsonstr);
}

    function getTodos() {
      localStorage.getItem('todo')
      let jsonstr = localStorage.getItem("todo");
      todo = JSON.parse(jsonstr);
      if (!todo || !todo.length) {
        todo = [];
      }
      else {
        renderTodoList();
      

} }

Here is a link to the codepen: https://codepen.io/david-webb/pen/yLeqydK

Can you help?

3

There are 3 answers

1
PatricNox On BEST ANSWER

This is because the current code seems to be removing the wrong item.

See scenario:


Localstorage: ["t","1", "2"];

-> Remove item #2 ("t")

Localstorage: ["t", "1"];

Output:

enter image description here


As you can see, the output shows ["t", "2"] thought the localstorage array is ["t", "1"].

This is because of the flawed logic in the removeItem function.

Try with this, instead.

//remove list item on click
function removeItem() {
  const item = this.parentNode;
  const value = this.parentNode.lastChild.textContent;
  
  todo = todo.filter(t => t !== value);
  this.parentNode.parentNode.removeChild(item);   
  saveTodos();
}

fiddle:

<input type = "text" style="font-size:25px;" id = "input" placeholder="Write here">

<button id = "addBtn" >Add item</button>

<ul id = "myUL">
</ul>

<script>
let todo = [];

renderTodoList();

document.getElementById('addBtn').addEventListener('click', function () {
  let value = document.getElementById('input').value;
  if (value) {
    todo.push(value);
    saveTodos()
    addInput(value);
  }
});

input.addEventListener("keypress", function(event) {
// Number 13 is the "Enter" key on the keyboard
if (event.keyCode === 13) {
  // Trigger the button element with a click
  document.getElementById("addBtn").click();
}
});


function addInput(text) {
  //add list item on click
  let listItem = document.createElement('li');
  let list = document.getElementById('myUL');
  let input = document.getElementById('input').value;
  let textNode = document.createTextNode(text);

  //create and append remove button
  let removeBtn = document.createElement("BUTTON");
  list.appendChild(removeBtn);
  removeBtn.className = "removeBtn";
  removeBtn.innerHTML = "Remove item";
  listItem.appendChild(removeBtn);
  list.appendChild(listItem);
  listItem.appendChild(textNode);
  document.getElementById("input").value = "";
  removeBtn.addEventListener('click', removeItem);
  console.log(todo);
}

//remove list item on click
function removeItem() {
  const item = this.parentNode;
  const value = this.parentNode.lastChild.textContent;
  
  todo = todo.filter(t => t !== value);
  this.parentNode.parentNode.removeChild(item);   
  saveTodos();
}

function renderTodoList() {
  if (!todo) return
  for (let i = 0; i < todo.length; i++) {
    let value = todo[i];
    addInput(value);
    console.log(value);
  }
}

function saveTodos() {
  let jsonstr = JSON.stringify(todo);
  localStorage.setItem('todo', jsonstr);
}

function getTodos() {
  localStorage.getItem('todo')
  let jsonstr = localStorage.getItem("todo");
  todo = JSON.parse(jsonstr);
  if (!todo || !todo.length) {
    todo = [];
  }
  else {
    renderTodoList();
  }
}



//cross out text on click
/*document.addEventListener('click', function (ev) {
  if (ev.target.tagName === 'LI') {
    ev.target.classList.toggle('checked');

  }
});*/

//renderTodoList();
getTodos();
</script>

0
Abid M.Rafiq On

This line has the error todo.splice(todo.indexOf(value, 1));

The reason is when you apply let item = this.parentNode.parentNode; you the UL element in the variable.

Fix:

While adding the item in addInput() create a span and put the text inside the span rather than creating textNode.

when removing from todo then you should use the innerText inside SPAN tag todo.splice(todo.indexOf(value, 1));

In the value variable you should have the todo item name.

1
Siva K V On

I think the problem is the usage of splice and indexOf.

For splice -- pass index, how may delete, new item

var todo = ["a", "b", "c"];
var value = "b"

// your code
todo.splice(todo.indexOf(value, 1));
console.log(todo)


var todo = ["a", "b", "c"];
var value = "b"
// correct way to delete
todo.splice(todo.indexOf(value), 1);

console.log(todo)