Why is the local storage value clear after a refresh? - javascript

const expenseForm = document.querySelector(".tracker-form"),
expenseName = document.querySelector(".tracker-name"),
expenseDate = document.querySelector(".tracker-date"),
expenseAmount = document.querySelector(".tracker-amount"),
expenseTable = document.querySelector(".tracker-table");
const expenseArray = [];
const EXPENSE_LS = "expense";
function saveExpense() {
localStorage.setItem(EXPENSE_LS, JSON.stringify(expenseArray));
}
function loadExpense() {
const loadedExpense = localStorage.getItem(EXPENSE_LS);
if (loadedExpense !== null) {
const parsedExpense = JSON.parse(loadedExpense);
createRow();
parsedExpense.forEach(expense => {
paintExpense(expense);
});
}
}
function createRow() {
const tr = document.createElement("tr");
expenseTable.appendChild(tr);
}
function paintExpense(text) {
const expenseObj = {};
function createData(text) {
const td = document.createElement("td");
const tr = document.querySelector("tr");
expenseTable.lastChild.appendChild(td);
td.innerHTML = text;
if (text === expenseName.value && text !== "") {
expenseObj.name = text;
} else if (text === expenseDate.value && text !== "") {
expenseObj.date = text;
} else if (text === expenseAmount.value && text !== "") {
expenseObj.amount = text;
}
}
createRow();
createData(expenseName.value);
createData(expenseDate.value);
createData(expenseAmount.value);
expenseArray.push(expenseObj);
saveExpense();
}
function handleSubmit(event) {
event.preventDefault();
paintExpense();
expenseName.value = "";
expenseDate.value = "";
expenseAmount.value = "";
}
function init() {
loadExpense();
expenseForm.addEventListener("submit", handleSubmit);
}
init();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Expense Tracker</title>
<link href="expense-tracker.css" rel="stylesheet">
</head>
<body>
<h1>Expense Tracker</h1>
<h3>Add A New Item</h3>
<form class="tracker-form">
<label for="tracker-name">Name: </label>
<input class="tracker-name" type="text" placeholder="What did you spend?">
<label for="tracker-date">Date: </label>
<input class="tracker-date" type="date">
<label for="tracker-amount">Amount: </label>
<input class="tracker-amount" type="text">
<input class="tracker-button" type="submit" value="Add Expense">
</form>
<table class="tracker-table">
<tr>
<th scope="col">Name</th>
<th scope="col">Date</th>
<th scope="col">Amount</th>
<th scope="col">Delete</th>
</tr>
</table>
<script src="expense-tracker.js"></script>
</body>
</html>
When i submit form, three input values are set in localStorage as an object in array. But when i refresh the page, all the value is clear and only the object itself left. I think loadExpense function has a problem but i don't know why. I googled about this problem and almost of them says stringify array when set it in local storage and parse it when i get it so i did it but it doesn't solve this problem. Why is this happen?

Problem:
When doing init() it call loadExpense() which reads data from local storage and iterates on each item and then paintExpense(expense); is getting called with expense as the parameter.
Now in paintExpense method, the passed expense object is not getting used to populate the tr and td rather you are calling
createData(expenseName.value);
createData(expenseDate.value);
createData(expenseAmount.value);
expenseArray.push(expenseObj) // <-- Empty object since the fields are empty on load
In this case all these expenseName, expenseDate, expenseAmount are empty that is they don't have value on page refresh. So inside createData the value for expenseObj is not getting set which means it remains empty.
Now the line expenseArray.push(expenseObj); is pushing empty object in array i.e [{}] which ultimately getting saved in you localstorage hence in localstoray empty objects are getting stored.
Solution:
Use passed expenseObj in paintExpense to populate object.
Sample Code
function loadExpense() {
const loadedExpense = localStorage.getItem(EXPENSE_LS);
if (loadedExpense !== null) {
const parsedExpense = JSON.parse(loadedExpense);
parsedExpense.forEach(expense => {
createRow(expense); //<-- Changed to createRow
});
}
}
// Added new method to create column
function createColumn(text) {
const td = document.createElement("td");
td.innerHTML = text;
return td;
}
// Changed createRow to create row and add columns (Replacement of paintExpense)
function createRow(expenseObj) {
const tr = document.createElement("tr");
tr.append(createColumn(expenseObj.name));
tr.append(createColumn(expenseObj.date));
tr.append(createColumn(expenseObj.amount));
expenseTable.appendChild(tr);
}
// Added new method to create object from html fields
function createData() {
const expenseObj = {};
expenseObj.name = expenseName.value;
expenseObj.date = expenseDate.value;
expenseObj.amount = expenseAmount.amount;
return expenseObj;
}
function handleSubmit(event) {
event.preventDefault();
const expenseObj = createData(); //<-- Create data from fields
expenseArray.push(expenseObj) //<-- Push into expense array
createRow(expenseObj); //<-- Create complete row with columns
saveExpense(); //<-- Moved Save from paint
expenseName.value = "";
expenseDate.value = "";
expenseAmount.value = "";
}

You should stringify your data and then put it into localStorage.
Example:
var testObject = { 'one': 1, 'two': 2, 'three': 3 };
// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));

Related

How can I perform Search Functionalities after loading the data from API using button?

Task is that display the response in table format on the HTML and also make a search box to search for data in the table along with sorting capability.
Data get's load but search functionalities is not working.
I need to click the button and it loads the data and perform the search accordingly.
var items = []
const load = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts')
const data = await response.json()
items = data
display(data)
} catch (error) {
document.getElementById('demo').innerHTML = `Error: ${error}`
}
search();
}
const display = (data) =>{
var table = "";
for (var i = 0; i < data.length; i++) {
var rowData ="<tr><td>"+data[i].userId+"</td><td>"+data[i].id+"</td><td>"+data[i].title+"</td><td>"+data[i].body;
table+= rowData;
}
document.getElementById("table").innerHTML = table;
}
// Search Function
const search = () =>{
const table = document.getElementById('table');
const mySearchField = document.getElementById('mySearchField');
// const searchCharacters = []
mySearchField.addEventListener('keyup', (e) => {
const searchString = e.target.value.toLowerCase();
const filteredItems = items.filter((data) => {
console.log(data)
return (
data.body.toLowerCase.includes(searchString) ||
data.title.toLowerCase.includes(searchString)
)
});
display(filteredItems);
});
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h3 id="demo">Let's Load the Data</h1>
<button type="button" id="btn" style="color: white; border-radius: 2px; background-color: blue;" onclick="load(); ">Load Now!</button>
<input id="mySearchField" name="search" placeholder="Search.." type="text">
<button id="mySearchButton">Search</button>
<br><br>
<table>
<thead>
<tr>
<th scope="col">UserId</th>
<th scope="col">Id</th>
<th scope="col">Title</th>
<th scope="col">Body</th>
</tr>
</thead>
<tbody id="table">
</tbody>
</table>
</body>
<script src="./script.js">
</script>
</html>
You need to make the following change in your Search function (add () brackets when using toLowerCase() function). It should fix the search issue.
return (
data.body.toLowerCase().includes(searchString) ||
data.title.toLowerCase().includes(searchString)
)
Whole function will look like this:
// Search Function
const search = () =>{
const table = document.getElementById('table');
const mySearchField = document.getElementById('mySearchField');
// const searchCharacters = []
mySearchField.addEventListener('keyup', (e) => {
const searchString = e.target.value.toLowerCase();
const filteredItems = items.filter((data) => {
console.log('11',data, searchString)
return (
data.body.toLowerCase().includes(searchString) ||
data.title.toLowerCase().includes(searchString)
)
});
display(filteredItems);
});
}

How do I let a user edit the textcontent of a specific cell in a table?

So I'm new to programming, and I'm creating a website where a user can enter information about their favourite books into a table.
However I've been trying to add an edit button feature where a user can click a button on a specific cell of the table and then be prompted to write in the replacement information.
So for example if they've already entered in the name of an author, they can click the edit button next to the info in the cell and they'll be prompted to enter in the replacement author's name, and it'll then reset the info in the cell in the table.
function addBooks() {
//Below is adding the users input information to the table.
let info = document.getElementById("author").value;
let info2 = document.getElementById("title").value;
let info3 = document.getElementById("genre").value;
let info4 = document.getElementById("review").value;
document.getElementById("author").value = "";
document.getElementById("title").value = "";
document.getElementById("genre").value = "";
document.getElementById("review").value = "";
let obj = {
author: info,
title: info2,
genre: info3,
review: info4,
};
let table = document.getElementById("table");
const row = table.insertRow(1);
var cell1 = row.insertCell(0);
var cell2 = row.insertCell(1);
var cell3 = row.insertCell(2);
var cell4 = row.insertCell(3);
//Below is the delete button which deletes a specific book/row.
var deleteButton = document.createElement("button");
deleteButton.classList.add("delete");
deleteButton.type = "button";
deleteButton.textContent = "Delete Book";
deleteButton.addEventListener("click", (event) => {
var row = deleteButton.parentNode.parentNode;
row.parentNode.removeChild(row);
});
cell1.innerHTML = `${obj.author}<button class="edit">Edit</button>`;
cell2.innerHTML = `${obj.title}<button class="edit">Edit</button>`;
cell3.innerHTML = `${obj.genre}<button class="edit">Edit</button>`;
cell4.innerHTML = `${obj.review}<button class="edit">Edit</button>`;
cell4.appendChild(deleteButton);
//Below here I am trying to addEvent listeners to the edit buttons that activate a function where the user can re-edit and enter new information into a specific cell.
const editButtons = document.getElementsByClassName("edit");
for (var i = 0; i < editButtons.length; i++) {
editButtons[i].addEventListener("click", (e) => {
editButtons.parentNode.innerHTML = prompt("Enter corrected info:");
});
}
}
Above is the Javascript code, but when I click on an edit button I get this error in the console :
books.js:47 Uncaught TypeError: Cannot set properties of undefined (setting 'innerHTML')
at HTMLButtonElement.<anonymous> (books.js:47:40)
I'm not sure what this means, but I was trying to be able to edit the text content of the parentNode. Is this the right way to to access and rewrite the text in the tables cells?
Here is also my html for reference.
<body>
<div class="container">
<h1 class="heading">Your Books</h1>
<p class="subHeading">Author</p>
<input type="text" id="author" />
<p class="subHeading">Title</p>
<input type="text" id="title" />
<p class="subHeading">Genre</p>
<input type="text" id="genre" />
<p class="subHeading">Reviews</p>
<input type="text" id="review" />
</div>
<button class="btn" onclick="addBooks()" id="button">Submit</button>
<table id="table">
<tr>
<th>Author</th>
<th>Title</th>
<th>Genre</th>
<th>Reviews</th>
</tr>
</table>
<script src="books.js"></script>
</body>
I hope that I've phrased things clear enough. Thanks a lot!
Never use innerHTML from unsanitized user inputs. Use textContent instead.
Function addBooks should be named addBook. Singular.
Use <thead> and specifically <tbody> as your target table element to insert rows into
Assign events on Element creation.
Create a separate ELNew_TD function to ease repetitive tasks
(TODO: don't use prompt() )
Here's a quick remake using some nifty DOM helper functions to make the code more readable:
// DOM utility functions
const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
const ELS = (sel, par) => (par || document).querySelectorAll(sel);
const EL = (sel, par) => (par || document).querySelector(sel);
// TASK:
const EL_author = EL("#author");
const EL_title = EL("#title");
const EL_genre = EL("#genre");
const EL_review = EL("#review");
const EL_table = EL("#table tbody");
const EL_add = EL("#button");
const ELNew_TD = (val) => {
const EL_td = ELNew("td");
const EL_span = ELNew("span", {
textContent: val
});
const EL_edit = ELNew("button", {
type: "button",
className: "delete",
textContent: "Edit",
onclick() {
val = prompt("Enter corrected info:");
val && (EL_span.textContent = val);
}
});
EL_td.append(EL_span, EL_edit);
return EL_td;
};
const addBook = () => {
const EL_tr = ELNew("tr");
const EL_btnDel = ELNew("button", {
type: "button",
textContent: "Delete",
onclick() { EL_tr.remove(); },
});
const EL_td5 = ELNew("td");
EL_td5.append(EL_btnDel);
EL_tr.append(
ELNew_TD(EL_author.value),
ELNew_TD(EL_title.value),
ELNew_TD(EL_genre.value),
ELNew_TD(EL_review.value),
EL_td5,
);
EL_table.append(EL_tr);
// Clear form
EL_author.value = "";
EL_title.value = "";
EL_genre.value = "";
EL_review.value = "";
};
EL_add.addEventListener("click", addBook);
label {display: block; padding: 5px 0;}
label span {display: inline-block; min-width: 100px;}
<div class="container">
<h1 class="heading">Your Books</h1>
<label><span>Author</span><input type="text" id="author"></label>
<label><span>Title</span><input type="text" id="title"></label>
<label><span>Genre</span><input type="text" id="genre"></label>
<label><span>Reviews</span><input type="text" id="review"></label>
</div>
<button class="btn" id="button">Add Book</button>
<table id="table">
<thead>
<tr>
<th>Author</th><th>Title</th><th>Genre</th><th>Reviews</th><th></th>
</tr>
</thead>
<tbody></tbody>
</table>
In the end I managed to fix the edit button so that it would remain functional no matter how many times it was used.
const editButtons = document.getElementsByClassName("edit");
for (var i = 0; i < editButtons.length; i++) {
editButtons[i].addEventListener("click", (e) => {
editButtons.parentNode.firstChild.innerHTML = prompt("Enter corrected info:");
});
}
}
This is the code that was used for the edit button function!
In your loop, use the “e” parameter you are passing into the event handler function to reference the elements (e.target).

Add a cell to my HTML table at end of each row as a true/false button

I'm trying to load and show a CSV in my HTML page using JS. I am able to show the data, but now I want to add the option to add an agree/disagree or check mark/x mark at the end of each row.
So for example, the first row will show some data, and after I looked at it, I will decide if I agree with it or not. After I click agree, the whole row's variable will be set to "true" for example.
So this is my HTML:
<html>
<body>
<input type="file" id="fileSelect" />
<div id="status">Waiting for CSV file.</div>
<table id="csvOutput"></table>
<script src="script.js"></script>
</body>
</html>
This is my script.js:
function buildHeaderElement (header) {
const headerEl = document.createElement('thead')
headerEl.append(buildRowElement(header, true))
return headerEl
}
function buildRowElement (row, header) {
const columns = row.split(',')
const rowEl = document.createElement('tr')
for (column of columns) {
const columnEl = document.createElement(`${header ? 'th' : 'td'}`)
columnEl.textContent = column
rowEl.append(columnEl)
}
return rowEl
}
function populateTable (tableEl, rows) {
const rowEls = [buildHeaderElement(rows.shift())]
for (const row of rows) {
if (!row) { continue }
rowEls.push(buildRowElement(row))
}
tableEl.innerHTML= ''
return tableEl.append(...rowEls)
}
function readSingleFile ({ target: { files } }) {
const file = files[0]
const fileReader = new FileReader()
const status = document.getElementById('status')
if (!file) {
status.textContent = 'No file selected.'
return
}
fileReader.onload = function ({ target: { result: contents } }) {
status.textContent = `File loaded: ${file.name}`
const tableEl = document.getElementById('csvOutput')
const lines = contents.split('\n')
populateTable(tableEl, lines)
status.textContent = `Table built from: ${file.name}`
}
fileReader.readAsText(file)
}
window.addEventListener('DOMContentLoaded', _ => {
document.getElementById('fileSelect').addEventListener('change', readSingleFile)
})
I can't figure out how to add the option I'm looking for at the end of each row, as well as how to mark each row as it's own variable.
To extend your code: after rowEl.append(columnEl), you could call a method to append a hard-coded TD/ TH and also append a checkbox.
As the columns are dynamically created, there is no way of knowing which columns store the unique key(s). Therefore you could store the entire row as a comma separated string as an attribute on the checkbox. Although you'll need to be careful the row data is not too long.
function buildRowElement(rowData, header) {
const columns = rowData.split(',')
const rowEl = document.createElement('tr')
for (column of columns) {
const columnEl = document.createElement(`${header ? 'th' : 'td'}`)
columnEl.textContent = column
rowEl.append(columnEl)
}
rowEl.append(provideColumnAgree(rowData, header))
return rowEl
}
function provideColumnAgree(rowData, header) {
const columnAgree = document.createElement(`${header ? 'th' : 'td'}`)
if (header) {
columnAgree.textContent = 'Agree?';
}
else {
const checkboxAgree = document.createElement(`input`)
checkboxAgree.setAttribute("type", "checkbox");
checkboxAgree.setAttribute("data-row", rowData);
columnAgree.append(checkboxAgree)
}
return columnAgree
}
A working example: https://jsfiddle.net/f74pxkor/

How do I save to local storage via vanilla JS

I can't seem to get local storage to work. The goal is to keep the todo list items on the page upon refresh. Every time I refresh the page it goes poof. The syntax seems right.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODO LIST</title>
<link rel="stylesheet" href="./styles/style.css">
</head>
<body>
<main id="main">
<h1>THE TO-DO LIST:</h1>
<form action="" id="add-task">
<label for="todo">Add Task:</label>
<input type="text" id="todo">
<button>Add Task</button>
</form>
<p class="center">To complete task, click on text.</p>
<ul id="task-list">
<li class="task-complete">example_1 <button>Remove Task</button></li>
</ul>
</main>
<script src="./script/index.js"></script>
</body>
</html>
const form = document.querySelector('#add-task');
const input = document.querySelector('#todo');
const taskList = document.querySelector('#task-list');
let taskID = 0;
taskList.addEventListener('click', function(e) {
if (e.target.tagName === 'BUTTON') {
e.target.parentElement.remove();
let inputTask = document.getElementById('todo');
localStorage.setItem('email', inputTask.value);
} else if (e.target.tagName === 'LI') {
e.target.classList.toggle('task-complete');
}
});
form.addEventListener('submit', function(e) {
e.preventDefault();
console.log(input.value);
const newTask = document.createElement('li');
const removeBtn = document.createElement('button');
let savedInput = input.value;
removeBtn.innerText = 'Remove Task';
newTask.innerText = input.value;
newTask.appendChild(removeBtn);
taskList.appendChild(newTask);
input.value = '';
console.log(localStorage);
});
.task-complete {
text-decoration: line-through;
}
Joshua, here are a few things from looking at your sample:
First, you're setting the localStorage to a single item, with the current input value, not a collection of tasks like an array
It also seems that you're not getting the saved data on page reload, that's why nothing happens when page reloads
Remember that you can only save strings to localStorage, in a todo list you might want to save an array (a collection of todos), but since you can't do it you need to convert it to a string while saving (JSON.stringify(yourArray) will help you with that), and parse it back to an Array when loading (JSON.parse)
const form = document.querySelector('#add-task');
const input = document.querySelector('#todo');
const taskList = document.querySelector('#task-list');
let taskID = 0;
let tasks = [] // here will hold your current todos collection
// a function that will retrieve the saved todos from local storage
//
// note that 'tasks' can be any string identifier that you want — 'todos'
// would also work — but you need to use the same for localStorage.getItem
// and localStorage.setItem
function getTasksFromLocalStorage(){
// it will return `null` if nothing's there
tasks = localStorage.getItem('tasks') || []
if (tasks) {
// convert it to an array so you can loop over it
tasks = JSON.parse(tasks)
}
}
function addTask(text) {
// CREATE DOM ELEMENTS
const newTask = document.createElement('li');
const removeBtn = document.createElement('button');
removeBtn.innerText = 'Remove Task';
// set the text to the provided value
newTask.innerText = text;
// append the remove button
newTask.appendChild(removeBtn);
// append it to the dom so we can see it
taskList.appendChild(newTask)
}
// on page load get tasks from local storage
// then loop over it, create the DOM elements and append them to
// the taskList
document.addEventListener('DOMContentLoaded', function() {
getTasksFromLocalStorage()
// if we have saved tasks, loop over them and render to the dom
tasks.forEach(function(savedTaskText) {
addTask(savedTaskText)
})
})
// then on your code, you need to update to push
// the current inputed `task` to the `tasks` collection (Array)
// then save the entire collection to the local storage
// then add the new task to the DOM
// and finally reset the input
form.addEventListener('submit', function(e) {
e.preventDefault();
console.log(input.value);
// save it to the current holding list
tasks.push(input.value)
// save a copy of the updated list to the localStorage, so when you
// reload the page you get saved items!
localStorage.setItem('tasks', tasks)
// add it to DOM
addTask(input.value);
// reset the input
input.value = '';
});
There's more things you need to do, if you want tasks to have unique ids (since, so you can remove them later), but the code was simplified for brevity of explanation (and yet you got a long answer anyways).
Here's so docs and suggested reading:
MDN Docs for LocalStorage
MDN Docs for JSON (parse and stringify)
There's plenty vanilla javascript tutorials (written and youtube) for "creating a todo lists using localStorage", that go into more detail than we can go in a SO answer, I suggest you skim through those as well!
Good luck and Happy coding ✌️
There are 2 problems with your code.
First, you are not saving each to-do task entered by user upon form submit. If you want to save each to-do task entered by user in localStorage, then modify the form submit handler as below:
form.addEventListener('submit', function(e) {
e.preventDefault();
const newTask = document.createElement('li');
const removeBtn = document.createElement('button');
let savedInput = input.value;
removeBtn.innerText = 'Remove Task';
newTask.innerText = input.value;
newTask.appendChild(removeBtn);
taskList.appendChild(newTask);
localStorage.setItem('Task'+taskID, input.value);
taskID++;
input.value = '';
});
Second, you are not utilizing the previously saved data in localStorage to show the list of to-dos that were entered by user before the page was loaded. You can achieve that by using below function code:
function showSavedToDos() {
const keys = Object.keys(localStorage);
let i = keys.length;
while (i--) {
const newTask = document.createElement('li');
const removeBtn = document.createElement('button');
removeBtn.innerText = 'Remove Task';
newTask.innerText = localStorage.getItem(keys[i]);
newTask.appendChild(removeBtn);
taskList.appendChild(newTask);
}
}
showSavedToDos();
You are not using de localStorage API, please take a look to this example. here I am using template to display the tasks. In the html file is the only change
<main id="main">
<h1>THE TO-DO LIST:</h1>
<form action="" id="add-task">
<label for="todo">Add Task:</label>
<input type="text" id="todo" />
<button>Add Task</button>
</form>
<p class="center">To complete task, click on text.</p>
<ul id="task-list">
<li class="task-complete">example_1 <button>Remove Task</button></li>
</ul>
</main>
<template id="task">
<li class="task-complete">
<span></span>
<button>Remove task</button>
</li>
</template>
In JavaScript I create a render function that will collect the task stored in localstorage. Populated when calling store(input.value) in the submit handler
const form = document.querySelector("#add-task");
const input = document.querySelector("#todo");
const taskList = document.querySelector("#task-list");
let taskID = 0;
taskList.addEventListener("click", function (e) {
if (e.target.tagName === "BUTTON") {
e.target.parentElement.remove();
let inputTask = document.getElementById("todo");
localStorage.setItem("email", inputTask.value);
} else if (e.target.tagName === "LI") {
e.target.classList.toggle("task-complete");
}
});
form.addEventListener("submit", function (e) {
e.preventDefault();
console.log(input.value);
const newTask = document.createElement("li");
const removeBtn = document.createElement("button");
let savedInput = input.value;
removeBtn.innerText = "Remove Task";
newTask.innerText = input.value;
newTask.appendChild(removeBtn);
taskList.appendChild(newTask);
store(input.value);
input.value = "";
console.log(localStorage);
});
function getTasks() {
return localStorage.tasks ? JSON.parse(localStorage.tasks) : [];
}
function store(task) {
const tasks = getTasks();
tasks.push(task);
localStorage.setItem("tasks", JSON.stringify(tasks));
}
function render() {
const tasks = getTasks();
tasks.forEach((task) => {
const newTask = createTask(task);
taskList.appendChild(newTask);
});
}
function createTask(task) {
const template = document.querySelector("#task");
const taskNode = template.content.cloneNode(true);
taskNode.querySelector("span").innerText = task;
return taskNode;
}
render();
The render function run every first render of the page, so tasks list will be populated

Storage and show multiple outputs

I have a simple text input where users type anything and after sumbitting text appear on a page and stays there, which I done with localStorage, but after refreshing the page only last typed input is showing, Ill post my code to be more specific:
HTML:
<body>
<input id="NewPostField" type="text" value="">
<button onclick="myFunction()">Post</button>
<div id="Posts"></div>
</body>
JavaScript:
function myFunction() {
var NewPostField =
document.getElementById("NewPostField");
var newPost = document.createElement("p");
localStorage.setItem('text',
NewPostField.value);
newPost.innerHTML = NewPostField.value;
var Posts = document.getElementById("Posts");
Posts.appendChild(newPost);
}
(function() {
const previousText = localStorage.getItem('text');
if (previousText) {
var NewPostField = document.getElementById("NewPostField");
NewPostField.value = previousText;
myFunction();
}
})();
Any help will be great!
It seems that your code is only storing the last value posted.
To store more than one post, one idea is to stringify an array of values to store in localStorage.
Then, parse that stringified value back into an array as needed.
Here's an example:
function getExistingPosts() {
// fetch existing data from localStorage
var existingPosts = localStorage.getItem('text');
try {
// try to parse it
existingPosts = JSON.parse(existingPosts);
} catch (e) {}
// return parsed data or an empty array
return existingPosts || [];
}
function displayPost(post) {
// display a post
var new_post = document.createElement("p");
new_post.innerHTML = post;
posts.appendChild(new_post);
}
function displayExistingPosts() {
// display all existing posts
var existingPosts = getExistingPosts();
posts.innerHTML = '';
inputPost.value = '';
if (existingPosts.length > 0) {
existingPosts.forEach(function(v) {
displayPost(v);
});
inputPost.value = existingPosts.slice(-1)[0];
}
}
function addPost(post) {
// add a post
var existing = getExistingPosts();
existing.push(post);
localStorage.setItem('text', JSON.stringify(existing));
displayPost(post);
}
function clearPosts() {
// clear all posts
localStorage.removeItem('text');
displayExistingPosts();
}
var posts = document.getElementById("posts");
var inputPost = document.getElementById("input_post");
var btnPost = document.getElementById('btn_post');
var btnClear = document.getElementById('btn_clear');
btnPost.addEventListener('click', function() {
addPost(inputPost.value)
});
btnClear.addEventListener('click', clearPosts);
displayExistingPosts();
<input id="input_post" type="text" value="">
<button type="button" id="btn_post">Post</button>
<button type="button" id="btn_clear">Clear</button>
<div id="posts"></div>
Since localStorage isn't supported in StackSnippets, here's a JSFiddle to help demonstrate.

Categories

Resources