Local storage in JS not loading items problem - javascript

I have a problem with the local storage it seems the items are getting saved to local storage but I cannot make it work to load at start.
Any tips and advice much appreciated.
I am posting the code below.
const input = document.getElementById('input');
const list = document.getElementById('list');
const addButton = document.getElementById('addButton');
const completed = document.getElementById("completed");
let LIST;
let id;
let loadSTORAGE = localStorage.getItem("STORAGE");
if (loadSTORAGE) {
LIST = JSON.parse(loadSTORAGE);
id = LIST.length;
loadList(LIST);
} else {
LIST = [];
id = 0;
}
function loadList() {
LIST.forEach(function() {
addTask();
});
}
addButton.addEventListener("click", addTask);
input.addEventListener("keyup", function(event) {
(event.keyCode === 13 ? addTask() : null)
})
function addTask() {
const newTask = document.createElement("li");
const delBtn = document.createElement("button");
const checkBtn = document.createElement("button");
delBtn.innerHTML = "<button>Reset</button>"
checkBtn.innerHTML = "<button>Done</button>"
if (input.value !== "") {
newTask.textContent = input.value;
list.appendChild(newTask);
newTask.appendChild(checkBtn);
newTask.appendChild(delBtn);
LIST.push({
name: input.value,
id: id,
});
id++
input.value = "";
console.log(LIST);
localStorage.setItem("STORAGE", JSON.stringify(LIST));
}
checkBtn.addEventListener("click", function() {
const parent = this.parentNode
parent.remove();
completed.appendChild(parent);
});
delBtn.addEventListener("click", function() {
const parent = this.parentNode
parent.remove();
});
}

You need to break out the logic of building the item and getting the value. Something like the following where the addTask just makes sure there is input and calls a method that builds an item. Now with the localstorage call, you can call just the code that builds the item.
const input = document.getElementById('input');
const list = document.getElementById('list');
const addButton = document.getElementById('addButton');
const completed = document.getElementById("completed");
const loadSTORAGE = localStorage.getItem("STORAGE");
const LIST = loadSTORAGE ? JSON.parse(loadSTORAGE) : [];
let id = LIST.length;
loadList(LIST);
function loadList() {
LIST.forEach(function(data) {
addTaskElement(data);
});
}
function addTask() {
if (input.value !== "") {
cons newItem = {
name: input.value,
id: id,
};
LIST.push(newItem);
id++;
localStorage.setItem("STORAGE", JSON.stringify(LIST));
input.value = "";
addTaskElement(newItem);
}
}
function addTaskElement(data) {
const newTask = document.createElement("li");
const delBtn = document.createElement("button");
const checkBtn = document.createElement("button");
delBtn.textContent = "Reset"
checkBtn.textContent = "Done"
newTask.textContent = data.name;
newTask.appendChild(checkBtn);
newTask.appendChild(delBtn);
list.appendChild(newTask);
}

Related

How to auto grow text on input value?

I have an input form field that outputs text on submit to another created input, essentially an editable todo list. I have tried to make the input text value auto grow, but cannot figure out how to do it. Right now the user has to scroll over to see the rest of the text on each list item. This should not be.
What I tried:
I have tried creating a span and attaching editableContent but that makes my input text disappear.
I have tried setting an attribute on max-length on the created input but cannot get it to work. What is the best way to accomplish auto growing the text input value?
Here is the full codepen
const createTodoText = (todo) => {
const itemText = document.createElement("INPUT");
// const itemText = document.createElement("span");
// itemText.contentEditable
// itemText.contentEditable = 'true'
itemText.classList.add("todoText");
itemText.value = todo.name;
itemText.addEventListener("click", (e) => {
e.currentTarget.classList.add("active");
});
// update todo item when user clicks away
itemText.addEventListener("blur", (e) => {
todo.name = e.currentTarget.value;
renderTodos();
});
return itemText;
};
There you go: -
// select DOM elements
const todoForm = document.querySelector(".todo-form");
const addButton = document.querySelector(".add-button");
const input = document.querySelector(".todo-input");
const ul = document.getElementById("todoList");
let todos = [];
todoForm.addEventListener("submit", function (e) {
e.preventDefault();
addTodo(input.value);
});
const addTodo = (input) => {
if (input !== "") {
const todo = {
id: Date.now(),
name: input,
completed: false
};
todos.push(todo);
renderTodos();
todoForm.reset();
}
};
const renderTodos = (todo) => {
ul.innerHTML = "";
todos.forEach((item) => {
let li = document.createElement("LI");
// li.classList.add('item');
li.setAttribute("class", "item");
li.setAttribute("data-key", item.id);
const itemText = createTodoText(item);
const cb = buildCheckbox(item);
const db = buildDeleteButton(item);
// if (item.completed === true) {
// li.classList.add('checked');
// }
li.append(cb);
li.append(db);
li.append(itemText);
ul.append(li);
});
};
const createTodoText = (todo) => {
const itemText = document.createElement("span");
itemText.setAttribute('role','textbox');
itemText.setAttribute('contenteditable',"true");
itemText.classList.add("todoText");
itemText.innerHTML = todo.name;
itemText.addEventListener("click", (e) => {
e.currentTarget.classList.add("active");
});
// update todo item when user clicks away
itemText.addEventListener("blur", (e) => {
todo.name = e.target.textContent;
renderTodos();
});
return itemText;
};
const buildCheckbox = (todo) => {
const cb = document.createElement('input');
cb.type = 'checkbox';
cb.name = 'checkbox';
cb.classList.add('checkbox');
cb.checked = todo.completed;
// checkbox not staying on current state ??
cb.addEventListener('click', function (e) {
if (e.target.type === 'checkbox') {
// todo.completed = e.target.value;
todo.completed = e.currentTarget.checked
e.target.parentElement.classList.toggle('checked');
}
});
return cb;
};
const buildDeleteButton = (todo) => {
const deleteButton = document.createElement("button");
deleteButton.className = "delete-button";
deleteButton.innerText = "x";
deleteButton.addEventListener("click", function (e) {
// duplicates children sometimes ??
const div = this.parentElement;
div.style.display = "none";
todos = todos.filter((item) => item.id !== todo.id);
});
return deleteButton;
};
// //------ Local Storage ------
function addToLocalStorage(todos) {}
function getFromLocalStorage() {}
// getFromLocalStorage();
This is the Javscript code part. In createTodoText, you can see the changes i've made. It's working according to what you want. What i've done is simple used 'span' instead of 'input'.
How about trying something like
if (todo.name.length) {itemText.size = todo.name.length;}

Why I get duplicated todos in todo list?

This is the js code
let form = document.getElementById('todoForm');
let input = document.getElementById('todoInput');
let btn = document.getElementById('btn');
let todos = [];
const loadTodos = () => {
let parent = document.getElementById('todoList');
todos.forEach(todo => {
let newLi = document.createElement('li');
newLi.innerHTML = `<li>${todo.text}</li>`
parent.appendChild(newLi);
})
}
btn.addEventListener('click', (e) => {
e.preventDefault();
let text = input.value;
let todo = {
id: todos.length + 1,
text: text,
complete: false,
}
todos.push(todo);
loadTodos();
})
window.onload = () => {
loadTodos();
}
When I add a todo for the first time its ok, but the seconed time will print the first todo again include the seconed.
example:
first todo
2.first todo
3.seconed todo
You should make another function to handle single todo added, below is your updated code
let form = document.getElementById('todoForm');
let input = document.getElementById('todoInput');
let btn = document.getElementById('btn');
let todos = [];
const loadTodos = () => {
let parent = document.getElementById('todoList');
todos.forEach(todo => {
let newLi = document.createElement('li');
newLi.innerHTML = `<li>${todo.text}</li>`
parent.appendChild(newLi);
})
}
const renderNewToDo = (todo) => {
let parent = document.getElementById('todoList');
let newLi = document.createElement('li');
newLi.innerHTML = `<li>${todo.text}</li>`
parent.appendChild(newLi);
}
btn.addEventListener('click', (e) => {
e.preventDefault();
let text = input.value;
let todo = {
id: todos.length + 1,
text: text,
complete: false,
}
todos.push(todo);
renderNewToDo(todo);
})
window.onload = () => {
loadTodos();
}

Issue with local storage for to-do list

I'm trying to add local storage to my to-do list. While refreshing the page does maintain the list item, the value comes back as undefined. I suspect it's something to do with the lack of an argument when I call the addInput function at the bottom, but I can't see a way around it.
In addition, if the toggled checked class is on and the item is crossed out, is there a way to store the class information?
I'd very much appreciate any help you can give me.
The offending code is below:
https://codepen.io/david-webb/pen/yLeqydK
function saveTodos () {
let jsonstr = JSON.stringify(todos);
localStorage.setItem('todos', jsonstr);
}
function getTodos () {
localStorage.getItem('todoList')
let jsonstr = localStorage.getItem("todos");
todos = JSON.parse(jsonstr);
if (!todos) {
todos = [];
}
}
//cross out text on click
document.addEventListener('click', function(ev) {
if (ev.target.tagName === 'LI') {
ev.target.classList.toggle('checked');
saveTodos ();
}
});
getTodos ();
addInput ();
Try this please:
<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 = [];
document.getElementById('addBtn').addEventListener('click', function () {
let value = document.getElementById('input').value;
if (value) {
todo.push(value);
saveTodos()
addInput(value);
}
});
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() {
let item = this.parentNode.parentNode;
let parent = item.parentNode;
let id = parent.id;
let value = parent.innerText;
todo.splice(todo.indexOf(value, 1));
saveTodos();
this.parentNode.parentNode.removeChild(this.parentNode);
console.log(todo)
}
function saveTodos() {
let jsonstr = JSON.stringify(todo);
localStorage.setItem('todos', jsonstr);
}
function getTodos() {
localStorage.getItem('todos')
let jsonstr = localStorage.getItem("todos");
todos = JSON.parse(jsonstr);
if (todos && !todos.length) {
todos = [];
}
else{
if(todos){
for(var intCounter = 0; intCounter < todos.length; intCounter++){
addInput(todos[intCounter]);
}
}
}
}
//cross out text on click
document.addEventListener('click', function (ev) {
if (ev.target.tagName === 'LI') {
ev.target.classList.toggle('checked');
saveTodos();
}
});
getTodos();
// addInput();
</script>
Call addInput within the getTodos function so that as soon as you're done with retreiving the list you print it.
This is what I changed:
function getTodos
function getTodos() {
localStorage.getItem('todos')
let jsonstr = localStorage.getItem("todos");
todos = JSON.parse(jsonstr);
if (todos && !todos.length) {
todos = [];
}
else{
if(todos){
for(var intCounter = 0; intCounter < todos.length; intCounter++){
addInput(todos[intCounter]);
}
}
}
}
Commented addInput().

Send Axios.get() Data to the HTML

I'm trying to make Axios.get() Send its Data to the HTML.
I'm Making To-Do app which as you guessed generates Todo list items on the page after entering value of the item in the input field(Also this items are being saved in the MongoDB)
I want to display every item from mongoDB in the style of Todo List items (With edit and delete button)
Any tips please?
let taskInput = document.getElementById("new-task");
let paginationBlock = document.getElementById("pagination");
let addButton = document.getElementsByTagName("button")[0];
addButton.setAttribute("id", "add");
let incompleteTaskHolder = document.getElementById("incomplete-tasks");
let paginationHolder = document.getElementById("pagination");
let listItem;
let label;
let editButton;
let deleteButton;
let editInput;
let checkBox;
let pageCount = 1;
let currentPage = 1;
let deleteCount = 0;
let storeData = [{}]
const setPageCount = () => {
const items = [...incompleteTaskHolder.children];
pageCount = Math.ceil(items.length / 5);
};
setPageCount();
const renderPagination = () => {
const items = [...incompleteTaskHolder.children]
paginationBlock.innerHTML = "";
for (let i = 1; i <= pageCount; i++) {
let pageBtn = document.createElement("button");
pageBtn.id = "pageBtn";
pageBtn.addEventListener("click", () => {
currentPage = i;
paginationDisplay();
});
pageBtn.innerText = i;
paginationBlock.append(pageBtn);
}
};
const paginationLimit = () => {
const items = [...incompleteTaskHolder.children];
if (items.length % 5 === 0) {
items.style.display = "none";
}
};
const paginationDisplay = () => {
const items = [...incompleteTaskHolder.children];
const start = (currentPage - 1) * 5;
const end = start + 5;
items.forEach((item, index) => {
if (index >= start && index < end) {
item.style.display = "block";
} else {
item.style.display = "none";
}
});
};
const sendData = () => {
let getValue = document.getElementById('new-task').value
axios.post('http://localhost:3000/add',{
todo : getValue
}).then(res => {
storeData.push({id : res.data._id})
console.log('res', res);
}).catch(err => {
console.log('err',err);
})
console.log(storeData)
}
const getAll = (data) => {
axios.get('http://localhost:3000').then(res => {
incompleteTaskHolder.innerHTML +=res.data
console.log('res',res.data);
}).catch(err => {
console.log('err',err);
})
}
getAll();
const deleteData = (id) => {
axios.delete(`http://localhost:3000/delete/${id}`,{
id : storeData
}).then(res => {
console.log('res',res)
}).catch(err => {
console.log('err',err)
})
};
let createNewTaskElement = function (taskString) {
listItem = document.createElement("li");
checkBox = document.createElement("input");
label = document.createElement("label");
editButton = document.createElement("button");
deleteButton = document.createElement("button");
editInput = document.createElement("input");
label.innerText = taskString;
checkBox.type = "checkbox";
editInput.type = "text";
editButton.innerText = "Edit";
editButton.className = "edit";
deleteButton.innerText = "Delete";
deleteButton.className = "delete";
listItem.appendChild(checkBox);
listItem.appendChild(label);
listItem.appendChild(editInput);
listItem.appendChild(editButton);
listItem.appendChild(deleteButton);
return listItem;
};
let addTask = function (showData) {
listItem = createNewTaskElement(taskInput.value);
document.getElementById("incomplete-tasks").appendChild(listItem);
bindTaskEvents(listItem, editButton);
setPageCount();
renderPagination();
paginationDisplay();
sendData();
};
let getInput = document.getElementById("new-task");
getInput.addEventListener("keyup", (event) => {
if (event.keyCode === 13) {
event.preventDefault();
document.getElementById("add").click();
}
});
let editTask = function () {
listItem = this.parentNode;
editInput = listItem.querySelector("input[type=text]");
label = listItem.querySelector("label");
containsClass = listItem.classList.contains("editMode");
if (containsClass) {
label.innerText = editInput.value;
} else {
editInput.value = label.innerText;
updateData();
}
listItem.classList.toggle("editMode");
};
let deleteTask = function () {
listItem = this.parentNode;
ul = listItem.parentNode;
ul.removeChild(listItem);
setPageCount();
renderPagination();
paginationDisplay();
deleteData();
};
addButton.onclick = addTask;
let bindTaskEvents = function (taskListItem) {
editButton = taskListItem.querySelector("button.edit");
deleteButton = taskListItem.querySelector("button.delete");
listItem = taskListItem.querySelector("label");
addButton = taskListItem.querySelector("button.add");
listItem.ondblclick = editTask;
editButton.onclick = editTask;
deleteButton.onclick = deleteTask;
};
for (let i = 0; i < incompleteTaskHolder.children.length; i++) {
bindTaskEvents(incompleteTaskHolder.children[i]);
}
Assuming you are getting a list of items as a response like ['todo1', 'todo2' 'todo3']. Let me know if your response is different in structure.
You can create a function that renders your todo list to HTML.
function createTodoList(todoArr) {
const container = document.createElement('div');
const todoList = document.createElement('ul');
document.getElementsByTagName('body')[0].appendChild(container);
container.appendChild(todoList);
todoArr.forEach(function(todo) {
const listItem = document.createElement('li');
listItem.textContent = todo;
todoList.appendChild(listItem);
});
}
// finally call the function with you response.data
createTodoList(res.data)
If you are getting a different response, you might have to

how to loop through each list and add local stored item in it

I have a Bookmark Page where I add edit and delete bookmarks. and I have stored these items in localStorage. the issue is in loaddata function where I get the stored data and save it back in newly created li. the li tag is storing all the inputs that I typed in just one list. what I want is each bookmark should be within its own list just like additem function. but I don't know how to achieve this
const search = document.querySelector('form input');
const input = document.querySelector('.add-text');
const container = document.querySelector('ul');
let items = null;
let currentItem = null;
let array = [];
const searchItems = function(e) {
if (items) {
let word = e.target.value.toLowerCase();
for (let item of items) {
if (item.firstChild.textContent.toLowerCase().indexOf(word) !== -1) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
}
}
}
const deleteItem = function(e) {
currentItem = null;
e.target.parentNode.remove();
input.value = '';
}
const editItem = function(e) {
currentItem = e.target.parentNode.firstChild;
input.value = currentItem.textContent;
}
const updateItem = function(e) {
if (currentItem) {
currentItem.textContent = input.value;
input.value = '';
}else{
alert('No Selected Text Here to Update');
return;
}
}
const addItem = function() {
let val = input.value;
if (val) {
let li = document.createElement('li');
let inner = '<h1 class="text">' + val + '</h1>';
inner += '<button class="delete">Delete</button>';
inner += '<button class="edit">Edit</button>';
array.push(inner);
let stringified = JSON.stringify(array);
localStorage.setItem('list', stringified);
li.innerHTML = inner;
container.appendChild(li);
input.value = '';
currentItem = li.firstChild;
items = document.querySelectorAll('li');
for (let del of document.querySelectorAll('.delete')) {
del.addEventListener('click', deleteItem);
}
for (let edit of document.querySelectorAll('.edit')) {
edit.addEventListener('click', editItem);
}
} else {
alert('please add some text');
return;
}
}
function loaddata(){
let li = document.createElement('li');
let stringified = localStorage.getItem('list');
let listitems = JSON.parse(stringified);
li.innerHTML = listitems;
container.appendChild(li);
console.log(li);
}
loaddata();
search.addEventListener('keyup', searchItems);
document.querySelector('#add').addEventListener('click', addItem);
document.querySelector('#update').addEventListener('click', updateItem);
Considering your list is an array, you need to loop through it and create adn populate elements within that loop. Try to edit your loaddata function this way:
// Mock content
let container = document.body
localStorage.setItem('list', JSON.stringify(['<h1>Foo</h1>', '<h1>Bar</h1>', '<h1>Baz</h1>']))
loaddata()
// Edited 'loaddata'
function loaddata() {
let stringified = localStorage.getItem('list');
console.log(stringified)
let listitems = JSON.parse(stringified);
for (let i = 0; i < listitems.length; i++) {
let li = document.createElement('li');
li.innerHTML = listitems[i];
container.appendChild(li);
console.log(li);
}
}
It can't be run like a code snippet in Stack Overflow sandbox due to security reasons (accessing Local Storage), so if you want to test it, consider copying to JSFiddle or so.

Categories

Resources