'Button onclick not Working Till Page Reload
I have A Very Small Application That add tasks to the page and save it to local storage so if i reload the page or close it everything will be at its place, the problem is on the created tasks i have a delete button , this button delete task from localstorage and dom,but i need to reload page first . This How the app looks
What i want is : can i delete tasks without reloading the page first ?
Full js code :
let myForm = document.getElementsByTagName("form")[0];
let input = document.getElementById("only");
let submit = document.getElementById("btn");
let resDiv = document.getElementsByClassName("tasks")[0];
function id () {
return '_' + Math.random().toString(36).substr(2, 9);
}
if (window.localStorage.tasks) {
for (let i = 0; i < JSON.parse(window.localStorage.tasks).length; i++) {
let myDiv = document.createElement("div");
let text = document.createTextNode(
JSON.parse(window.localStorage.tasks)[i].title
);
let del = document.createElement("button");
let delText = document.createTextNode("Delete");
del.append(delText);
del.className = "del";
del.dataset.id = JSON.parse(window.localStorage.tasks)[i].id;
myDiv.className = "myDiv";
myDiv.append(text, del);
resDiv.append(myDiv);
}
}
myForm.onsubmit = function (e) {
if (input.value !== "") {
let myDiv = document.createElement("div");
let text = document.createTextNode(input.value);
let del = document.createElement("button");
let delText = document.createTextNode("Delete");
del.append(delText);
del.className = "del";
del.dataset.id = id();
myDiv.className = "myDiv";
myDiv.append(text, del);
resDiv.append(myDiv);
let push = JSON.parse(window.localStorage.getItem("tasks")) || [];
push.push({ id: del.dataset.id, title: input.value });
window.localStorage.setItem("tasks", JSON.stringify(push));
}
e.preventDefault();
};
let tasksArray = JSON.parse(window.localStorage.tasks);
resDiv.addEventListener("click", function (e) {
for (let j = 0; j < tasksArray.length; j++) {
if ( e.target.dataset.id === tasksArray[j].id) {
tasksArray.splice(tasksArray.indexOf(tasksArray[j]), 1);
window.localStorage.setItem("tasks", JSON.stringify(tasksArray));
e.target.parentElement.remove();
}
}
});
Html :
<form action="">
<input type="text" name="" id="only" />
<input type="submit" value="Add Tasks" id="btn" />
</form>
<div class="tasks"></div>
Note : I am new to javaScript i hope You Understand if i did some silly mistakes ^_^. Thanks For trying to help :D forgive my grammar .
Solution 1:[1]
Your code is very hard to read. So, I ended up re writing the whole thing using good conventions and tricks that you can use in the future. Take notes :)
I'm assuming you're in charge of the code that assigns the ids that you didn't give us. So I made one particularly for this example.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<form id="my-form" action="">
<input type="text" name="" id="input-box" />
<input type="submit" value="Add Tasks" id="submit-button" />
</form>
<div id="task-list" class="tasks"></div>
<script>
const myForm = document.getElementById("my-form");
const inputBox = document.getElementById("input-box");
const taskList = document.getElementById("task-list");
// Assuming your are handling this function.
// You can ignore this part
function Id() {
const uid =
new Date().toISOString().replaceAll(/[-:TZ]/g, ".") +
Math.random().toString().substring(2, 7);
return uid.split(".").join("");
}
// Set the tasks everytime the application is refreshed
window.onload = function () {
// The tasks in your local storage. Local storage stores data in string
// only so you need to use JSON.parse to convert it into readable array
// I'm also setting the default value to [] in case javascript cannot find
// the tasks
const tasks = JSON.parse(localStorage.getItem("tasks")) || [];
tasks.forEach(({ id, title }) => {
// Reusable renderTasks function to render the tasks
const task = renderTasks(id, title);
taskList.append(task);
});
};
// Reusable function to render the tasks.
function renderTasks(id, title) {
const taskParent = document.createElement("div");
taskParent.style.display = "flex";
taskParent.id = id;
const taskTitle = document.createElement("p");
taskTitle.innerText = title;
// You don't need to set Id's in your case. You can just assign a
// function to the delete button and remove the parent within the
// functon itself
const deleteButton = document.createElement("button");
deleteButton.innerText = "DELETE";
deleteButton.onclick = function () {
const tasks = JSON.parse(localStorage.getItem("tasks"));
taskParent.remove();
// Array filter. Return a new list without the deleted task
const newTaskList = tasks.filter((task) => task.id !== id);
localStorage.setItem("tasks", JSON.stringify(newTaskList));
};
// I'm using append because with appendChild you can't append more than
// 2 html elements at the same time
taskParent.append(taskTitle, deleteButton);
return taskParent;
}
// 1. render the task
// 2. Append the task to the list
// 3. Set the title in the localStorage
myForm.onsubmit = function (e) {
e.preventDefault();
const tasks = JSON.parse(localStorage.getItem("tasks")) || [];
const id = Id();
const title = inputBox.value;
const task = renderTasks(id, title);
taskList.append(task);
localStorage.setItem(
"tasks",
JSON.stringify([...tasks, { id, title }])
);
};
</script>
</body>
</html>
More on filter: Array.prototype.filter()
Solution 2:[2]
You didn't define myForm
, and the form doesn't have a selector. The form also doesn't have the name set, so if it does go to the server, then it won't be able to read anything. Your code formatting is also very weird, I'd recommend running it through a beautifier like FreeFormatter so it's easier to read and edit. The code below fixes all of the issues except for the last one which should be run through the whole code.
const myForm = document.getElementById('myForm');
myForm.onsubmit = function (e) {
if (input.value !== "") {
let myDiv = document.createElement("div");
let text = document.createTextNode(input.value);
let del = document.createElement("button");
let delText = document.createTextNode("Delete");
del.append(delText);
del.className = "del";
del.dataset.id = id();
myDiv.className = "myDiv";
myDiv.append(text, del);
resDiv.append(myDiv);
let push = JSON.parse(window.localStorage.getItem("tasks")) || [];
push.push({ id: del.dataset.id, title: input.value });
window.localStorage.setItem("tasks", JSON.stringify(push));
}
e.preventDefault();
};
<form action="/to/page.php" method="either put GET or POST here" id="myForm">
<input type="text" name="tasks" id="only" />
<input type="submit" value="Add Tasks" id="btn" />
</form>
I would recommend looking at some Javascript tutorials and documentation from:
MDN (Mozilla Developer Network docs)
w3schools sometimes has issues, but it's one of the easiest ways to learn coding
DevDocs can be useful at times
Note: If the page the form is going to is the same page, you should change your file extension to PHP from HTML (you will need a web server or server software like xampp for this) and you should replace action="/to/page.php"
with action="<?php echo $_SERVER['PHP_SELF']; ?>"
.
For the deletion, you should force the reload of a page, or use e.innerHTML = '';
or e.style.display = 'none';
in the function to remove the task.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Dharman |
Solution 2 |