how to remove data from array in local storage? - javascript

How to remove particular data when user click on delete from array stored in local storage ?
the key named title and description in both data are stored in form of array.
this is my script file
let title, description;
function validate() {
title = document.getElementById('title').value;
description = document.getElementById('description').value;
if (title == '') {
alert("Please add title");
} else if (description == '') {
alert("Please add description");
} else {
document.getElementById("myform").reset();
console.log(title);
console.log(description);
store(title, description);
}
}
function store(title, description) {
// load the existing values (default to an empty array if not exist)
let _title = JSON.parse(localStorage.getItem("title") || "[]")
let _description = JSON.parse(localStorage.getItem("description") || "[]")
_title.push(title)
_description.push(description)
localStorage.setItem("title", JSON.stringify(_title))
localStorage.setItem("description", JSON.stringify(_description))
window.location.reload()
}
get_title = JSON.parse(localStorage.getItem("title"))
get_description = JSON.parse(localStorage.getItem("description"))
let table1;
for (i = 0; i < get_title.length; i++) {
if (get_title[i] == null) {
console.log("null")
} else {
table1 += `
<tr>
<th scope="row">${i + 1}</th>
<td id="tit">${get_title[i]}</td>
<td id="descripti">${get_description[i]}</td>
<td>
**
<button type="button"
class="btn btn-sm btn-danger"
onclick="del(${i})">
Delete
</button>
**
</td>
</tr>`
}
}
document.getElementById('table1').innerHTML = table1;
function del(i) {
localStorage.removeItem(`title[${i}]`)
localStorage.removeItem(`description[${i}]`)
window.location.reload()
}
please help me to remove this items.

localStorage and sessionStorage are both key, value storages where both key and value are strings.
You will have to read the arrays
let titles = JSON.parse(localStorage.getItem("title"));
let descs = JSON.parse(localStorage.getItem("descs"));
titles.splice(i, 1);
descs.splice(i, 1);
localStorage.setItem("title", JSON.stringify(titles));
localStorage.setItem("description", JSON.stringify(descs));
I would suggest you store a single array with objects inside like this:
localStorage.setItem('items', JSON.stringify([{ title: 'title1', descirption: 'description1' }]));
Otherwise you risk to have the arrays length out of sync.
Then when you read the array:
let get_items = JSON.parse(localStorage.getItem('items'));
...
get_items[i].title; //reads title
get_items[i].description; //reads description

Related

Button adding user input to the array. Then typing out the data in array to a <div>

I'm fairly new to coding so please ignore any unwritten rules I might be missing.
Any feedback is appreciated.
Basically, I have three text inputs, Name:, Age:, and Password:
If not all fields are filled and error message will occur, but if everything is filled in and the user presses the button I need the information to be saved to an array, and for the information (only Name: & Age:) to be typed out below, along with two other "personas" that are to be added via (Push) method.
However, I'm not getting these different stages to work together. I am receiving different errors each time I change something. As previously stated I am a novice within coding and will take any help I can get.
function buttonclick() {
validate();
addToArray();
}
function validate() {
var name = document.getElementById("NameInput");
var age = document.getElementById("AgeInput");
var password = document.getElementById("PasswordInput");
if (name.value == "" || password.value == "" || age.value == "") {
alert("Field is required");
return false;
} else {
true;
}
if (password.value == "IHM") {
true;
} else {
alert("Not a valid password")
return false;
}
}
function addToArray() {
let persons = [];
let person1 = {
Uname: "Marcus",
Uage: 34
}
let person2 = {
Uname: "Cihan",
Uage: 35
}
// Gets name from the input
let Uname = document.getElementById("NameInput").value;
// Gets age from the input
let Uage = document.getElementById("AgeInput").value;
// Adds antoher name to the array?
persons.push(person1, person2);
// Sorts the array
persons.sort();
/* Is this needed?
const write = () => {
NameInput.forEach()
AgeInput.forEach()
}*
<div>
<input type="text" placeholder="Name" id="NameInput">
</div>
<div>
<input type="number" placeholder="Age" id="AgeInput">
</div>
<div>
<input type="password" placeholder="Password" id="PasswordInput">
</div>
<button onclick="buttonclick()" type="button">Submit</button>
<div id="output"></div>
I see your code in the vsCode, and your array gets the two objects if you check in the console, I add an object of user name and age- from inputs. I hope that im understand.. that my code:
enter code here function buttonclick() {
validate(addToArray);
}
var uname = document.getElementById("NameInput");
var age = document.getElementById("AgeInput");
function validate(cb) {
var password = document.getElementById("PasswordInput");
if (name.value == "" || password.value == "" || age.value == "") {
alert("Field is required");
return false;
} else {
true;
}
if (password.value == "IHM") {
true;
} else {
alert("Not a valid password")
return false;
}
cb();
}
function addToArray() {
let persons = [];
let person1 = {
Uname: "Marcus",
Uage: 34
}
let person2 = {
Uname: "Cihan",
Uage: 35
}
// Gets name from the input
let objOfUserInputs = {};
objOfUserInputs.uname = uname.value;
objOfUserInputs.uage = age.value;
// Gets age from the input
let Uage = document.getElementById("AgeInput").value;
// Adds antoher name to the array?
persons.push(person1, person2, objOfUserInputs);
// Sorts the array
persons.sort();
console.log(persons);
}
First step: You don't need to write true in the conditionals, you could just return if you don't need to check the returned value
eg.:
For the first conditional, you don't even need the else part
if (name.value == "" || password.value == "" || age.value == "") {
alert("Field is required");
return
}
For the second conditional
if (password.value == "IHM"){
return true
} else {
alert ('Wrong password')
}
You could even write it like this, since if the condition is met, the function will return and the alert won't trigger
if (password.value == "IHM"){
return true
}
alert ('Wrong password')
Try it out.
Then you want to append those values to the array (if i understood correctly) and you want them to be displayed, alongside with the others.
I suggest you create a similar object and then push that object to the array, then you can sort it
So, create the object from the user input:
let Uname = document.getElementById("NameInput").value;
let Uage = parseInt(document.getElementById("AgeInput").value);
//You need to use parseInt() if you want that item to be an integer
let person3 = {
Uname: Uname,
Uage: Uage
}
And then push every object to the array
persons.push(person1, person2, person3);
//return the array
return persons
to sort the array, by name i imagine, just using sort would not suffice, as you want to sort on the 'name' property, so you have to pass a function to sort that orders the items by their name.
You can check it here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
persons.sort(function (a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
The last step, if i understand correctly, is placing all the items, in the ordered array, inside the output div, so let's keep the write() function.
You have to iterate through each element, and then you need to insert the HTML that you have created inside the 'output' div.
There are a few ways to to this, you can create elements in the js, or you can append the HTML directly to the div.
Let's say you want to place them in an unordered list.
//pass the result from the addToArray() funtion to the write() function
function write(persons){
let output = document.getElementById('output')
//clean output div otherwise everytime it will append new content
output.innerHTML = ""
let ul = document.createElement('ul')
//Iterate
for( let i of persons){
let li = document.createElement('li')
li.innerHTML = `${i.Uname} - ${i.Uage}`
ul.appendChild(li)
}
output.appendChild(ul)
}
and finally the onclick function, you need to make sure that everything is as you want before adding it to the output div, so check if the verify function has returned true(or whatever you prefer), and the create the array and write it to the div
function buttonclick() {
if (validate() === true){
write(addToArray())
}
}
here is it in full
<body>
<div>
<input type="text" placeholder="Name" id="NameInput">
</div>
<div>
<input type="number" placeholder="Age" id="AgeInput">
</div>
<div>
<input type="password" placeholder="Password" id="PasswordInput">
</div>
<button onclick="buttonclick()" type ="button">Submit</button>
<div id="output"></div>
<script>
function buttonclick() {
if (validate() === true){
write(addToArray())
}
}
function validate() {
var name = document.getElementById("NameInput");
var age = document.getElementById("AgeInput");
var password = document.getElementById("PasswordInput");
if (name.value == "" || password.value == "" || age.value == "") {
alert("Field is required");
return
}
if (password.value == "IHM") {
return true
}
alert("Not a valid password")
}
function addToArray() {
let persons = [];
let person1 = {
Uname: "Marcus",
Uage: 34
}
let person2 = {
Uname: "Cihan",
Uage: 35
}
// Gets name from the input
let Uname = document.getElementById("NameInput").value;
// Gets age from the input
let Uage = parseInt(document.getElementById("AgeInput").value);
//Create the object
let person3 = {
Uname: Uname,
Uage: Uage
}
// Adds antoher name to the array?
persons.push(person1, person2, person3);
// Sorts the array
persons.sort(function (a, b) {
var nameA = a.Uname.toUpperCase(); // ignore upper and lowercase
var nameB = b.Uname.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
return persons
}
function write(persons) {
let output = document.getElementById('output')
//clean output div otherwise everytime it will append new content
output.innerHTML = ""
let ul = document.createElement('ul')
//Iterate
for (let i of persons) {
let li = document.createElement('li')
li.innerHTML = `${i.Uname} - ${i.Uage}`
//Append items to ul
ul.appendChild(li)
}
//Append ul to the 'output' div
output.appendChild(ul)
}
</script>
</body>
There are many ways you can accomplish this, i have tried to stay as close as possible to your example so you can understand better, i hope it'll help you, have a good day.

Angular Input Is Not Saved

In my app, I have a table where the user can enter some stuff to an input field and save them. In the network, the stuff he entered are saved but whenever I refresh the page, the field is empty as if nothing has been entered there. Here is my code, what is wrong with it, and how can I fix it?
HTML:
<ng-container matColumnDef="FilePath">
<th mat-header-cell *matHeaderCellDef> Dosya Yolu </th>
<td mat-cell *matCellDef="let row; let i = index">
<a href (click)="$event.preventDefault()" *ngIf="EditIndex != i">{{row.FilePath}}</a>
<mat-form-field floatLabel="never" *ngIf="EditIndex == i" class="w-100-p">
<input matInput name="FilePath" [(ngModel)]="row.FilePath" type="text">
</mat-form-field>
</td>
</ng-container>
<button mat-icon-button *ngIf="EditIndex != i" (click)="editRow(row, i)">
<mat-icon>edit</mat-icon>
</button>
<button mat-icon-button *ngIf="EditIndex == i"
(click)="editRow(row, undefined)">
<mat-icon>done</mat-icon>
</button>
TS:
testList: ILabConditionResult[] = [];
HPLCFiles: ILabAnalysisFile[] = [];
dataSource: MatTableDataSource<ILabAnalysisFile>;
constructor(){
let data: ILabAnalysisFile[] = [];
this.dataSource = new MatTableDataSource(data);
}
setResponse(response: ILabConditionResult[]) {
if (response) {
response = response.sort((a, b) => {
return a.SequenceNumber - b.SequenceNumber;
});
}
this.testList = response;
if (this.testList && this.testList.length > 0) {
this.HPLCFiles = this.testList[0].HPLCFiles;
this.dataSource.data = this.testList[0].HPLCFiles;
}
}
save(){
this.labConditionResult.HPLCFiles = this.dataSource.data;
this.testList[0].HPLCFiles = this.dataSource.data;
this._labService
.saveAndGetLabTestResultList(this.testList)
.subscribe((response: ILabConditionResult[]) => {
response = response.sort((a, b) => {
return a.SequenceNumber - b.SequenceNumber;
});
this.setResponse(response);
this.setIndex();
response.forEach((x) => {
this.setLabConditionResult(x);
});
}
addNewWorkItem() {
let tempData = this.dataSource.data.splice(0);
tempData.unshift({});
this.dataSource = new MatTableDataSource(tempData);
this.EditIndex = 0;
}
editRow(row: ILabAnalysisFile, index: number) {
if (index == undefined) {
if (
!row.FilePath
) {
return;
}
this.fileList = [];
} else {
this.fileList = [];
}
this.EditIndex = index;
}
The browser can hold data until DOM refreshes, I would recommend save it in localstorage of the browser
// This will store data where Key is identifier and Value can be a dynamic variable
localStorage.setItem(Key, value); // Key & Value should be string before storing
// Retrieve the Value of Key
localStorage.getItem(Key) // String
So according to your code:
// Store Test list from whatever to string
localStorage.setItem("TestList", JSON.stringify(this.testList));
// Retrieve testlist value and change from string to original form
JSON.parse(localStorage.getItem("TestList"));

Sort array of objects by key values and displaying them on a HTML element

I'm making a movie sorter list, you enter the title and then the rating and it will show you the movies in order by rating. I have an array of objects and I managed to sort the array by rating, but I can't find a way to actually display the array in order on the HTML DOM.
I've tried for loops and forEach's but they don't work the way I want.
const movieTitle = document.querySelector(".movie-title");
const movieRating = document.querySelector(".movie-rating");
const movieList = document.querySelector(".movie-list");
const sortBtn = document.querySelector(".btn");
let movieStorage = [];
function sendMovie() {
if(event.keyCode == 13) {
if(movieTitle.value != "" && movieRating.value != "") {
title = movieTitle.value;
rating = parseInt(movieRating.value);
movieStorage.push({
title: title,
rating: rating
});
// If rating of a is bigger than rating of b return 1, if not return -1
movieStorage.sort((a, b) => (a.rating > b.rating) ? -1 : 1);
console.log(movieStorage);
addMovieToList(title, rating);
movieTitle.value = "";
movieRating.value = "";
} else {
console.log("Fields missing");
}
}
}
function addMovieToList(title, rating) {
const div = document.createElement("div");
div.className = "list-items";
div.innerHTML = `
<div class="item-title">
<p>${title}</p>
</div>
<div class="item-rating">
<p>${rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
movieList.appendChild(div);
}
function sortByRating(element) {
for(let i = 0; i < movieStorage.length; i++) {
element.innerHTML = `
<div class="item-title">
<p>${movieStorage[i].title}</p>
</div>
<div class="item-rating">
<p>${movieStorage[i].rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
}
}
document.addEventListener("click", (e) => {
const deleteIcon = e.target;
const item = document.querySelector(".list-items");
if(deleteIcon.classList.contains("delete")) {
deleteIcon.parentElement.parentElement.remove(item);
}
})
tldr demo
After sorting the array, you need a way to reference movie divs to sort them. There are many ways to do it, what I chose is using id. When you create movie <div>, give it an ID unique for each movie name:
// Simple function to generate hash number for each string
function hashStr(stringValue) {
var hash = 0, i, chr;
if (stringValue.length === 0) return hash;
for (i = 0; i < stringValue.length; i++) {
chr = stringValue.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
}
const MOVIES = [
{name: "a", rating: 3},
{name: "b", rating: 6},
{name: "c", rating: 3},
{name: "d", rating: 2},
{name: "e", rating: 1},
];
function showMovies() {
const moviesDiv = document.querySelector("#movies");
for(const movie of MOVIES)
{
const id = "movie-"+hashStr(movie.name);
// If there's no element with the ID, we need to create the DIV for the movie
if(!document.querySelector("#"+id)) {
const elm = document.createElement("div");
elm.appendChild(new Text(movie.name + " ("+movie.rating+"/10)"));
elm.id = id;
elm.classList.add("movie");
moviesDiv.appendChild(elm);
}
}
}
Then, when sorting, you can reference each movie by ID:
// Sort movies using given property (eg. "name")
// The second param determines sort direction
function sortBy(property, ascending=true) {
MOVIES.sort((a,b) =>{
return cmp(a[property], b[property], ascending);
});
// Now after sorting the array, we can sort the HTML elements
const moviesDiv = document.querySelector("#movies");
let lastMovie = null;
for(const movie of MOVIES)
{
const id = "#movie-"+hashStr(movie.name);
const movieDiv = document.querySelector(id);
console.log(id, movieDiv);
// If created
if(movieDiv) {
// remove and append after last processed movie (for the first movie, this will append to top)
moviesDiv.insertBefore(movieDiv, lastMovie);
}
}
}
// Compare string and number, makes no sense for other types
function cmp(a,b, ascending=true) {
if(typeof a=='number' && typeof b == "number") {
return ascending ? a-b : b-a;
}
else if(typeof a=='string' && typeof b == "string"){
return (ascending ? 1 : -1) * a.localeCompare(b);
}
else {
return 0;
}
}
When you add a movie, you just call sort again. You will need to remember the last sorting parameters for that.
Your sort will work fine. The problem is that after you've sorted you can't just display that movie, you have to redisplay the entire list. You're almost there with your sortByRating method, but it doesn't recreate the entire list correctly. Try something like:
function showMoviesList(element) {
let innerHTML = "";
for (let i = 0; i < movieStorage.length; i++) {
innerHTML += `
<div class="item-title">
<p>${movieStorage[i].title}</p>
</div>
<div class="item-rating">
<p>${movieStorage[i].rating}</p>
</div>
<div class="item-delete">
<i class="fa fa-trash trash-icon delete"></i>
</div>
`;
}
element.innerHTML = innerHTML;
}
This resets the inner HTML of the element to the complete movie list in order every time it's called.
Now call showMoviesList(movieList) instead of calling addMovieToList in sendMovie.

How to keep a specific type of element from being stored in an array?

I have code that has a user input numbers that are stored in an array. I would like to know how to prevent a user from entering a negative number in the array and showing in red (preferably red text below input) that they can't enter a negative number
I was able to get the array to identify what type of integer is put into an array with an if... else statement, but I can't seem to get the array to pop off the negative number.
<input type="number" id="user_input">
<button type="button" id="myBtn">Click to store</button>
<script>
const myArray = [];
const addData = () => {
let inputData = document.getElementById('user_input');
myArray.push(parseInt(inputData.value));
console.log(myArray);
if (inputData.value <= 0) {
console.log("negative int")
} else if (inputData.value == 0) {
console.log('nothing entered')
} else {
console.log("positive int")
}
inputData.value = "";
}
document.getElementById('myBtn').addEventListener('click', addData);
</script>
You could take the numerical value and check if the string is given or if this value is an integer value, or negative. Then you need function for showing a wanted message with a certain color.
This solution features an exit early, exit often paradigm, where the function takes a condition and exits if the condition is met, to prevent to go to the natural end of the function by using a chained else ... if ... else structure.
In short, this approach works without else parts, which is here possible.
const
myArray = [],
addData = () => {
const setMessage = (string, color = '#000000') => {
message.style.color = color;
message.innerHTML = string;
}
let inputData = document.getElementById('user_input'),
message = document.getElementById('message'),
value = +inputData.value;
if (inputData.value === '') {
setMessage('nothing entered', '#bb0000');
return;
}
inputData.value = "";
if (value !== Math.floor(value)) {
setMessage('no int', '#bb0000');
return;
}
if (value <= 0) {
setMessage('negative int', '#bb0000');
return;
}
myArray.push(value);
console.log(myArray);
setMessage('positive int');
}
document.getElementById('myBtn').addEventListener('click', addData);
<input type="number" id="user_input">
<button type="button" id="myBtn">Click to store</button>
<p id="message"></p>
The issue here is that you're pushing the value in the array before checking for its type. You just have to do it like this to prevent negative numbers to get inside the array :
const myArray = [];
const addData = () => {
let inputData = document.getElementById('user_input');
console.log(myArray);
if (inputData.value <= 0) {
console.log("negative int")
} else if (inputData.value == 0) {
console.log('nothing entered')
} else {
console.log("positive int")
myArray.push(parseInt(inputData.value));
}
inputData.value = "";
}
document.getElementById('myBtn').addEventListener('click', addData);
Or, very simply <input type="number" id="user_input" min="0">

Delete duplicate array element

I am working on a program that records customer name and status(child/adult), the program allows add, display and delete customer records from array. However, if user enters the same name and status e.g:
Name: james, status: adult
Name: james, status: adult
I want the function to delete just one record,but now it delete both of them, do i have to add break here? Please help.
PS: I can't use any inbuilt JavaScript functions such as slice(),delete(), concat(), join(), pop(), push(), reverse(), shift(), slice(), sort(), splice(), toString(), unshift() or valueOf()
const MAX_CUSTOMERS = 5;
//create new Array
var customerList = new Array();
function addCustomer() //add customer
{
if (customerList.length >= MAX_CUSTOMERS) //check max customers
alert('Sorry, no more than ' + String(MAX_CUSTOMERS) + ' customers are allowed on the trampoline.')
else
{
var newIndex = customerList.length; //add new user
customerList[newIndex] = new Object;
customerList[newIndex].name = prompt('What is the customer\'s name?'); //ask user enter their name
customerList[newIndex].status = prompt('Are you a Child or an Adult?'); //ask user enter their status
while (!(customerList[newIndex].status == 'child' || customerList[newIndex].status == 'adult')) //check user is child or adult
{
customerList[newIndex].status = (prompt('Error! Please Enter \'child\' or \'adult\':'));
}
}
}
function displayAllCustomers() //display customers
{
var message = ''; //create message
for (var i = 0; i < customerList.length; i++) //loop customers
{
message += 'Name:' + customerList[i].name + ', Status: ' + String(customerList[i].status) + '. \n'; //add customer to message
}
if (message == '') //check message
message = 'Sorry, there are no customer to display!';
alert(message); //output message
}
function identifyThenDeleteCustomer() //identify then delete customer
{
var customerName = prompt('Enter the name of the customer to delete:'); //get customer name
var customerStatus = prompt('Enter \'child\' or \'adult\':'); //get customer status
while (!(customerStatus == 'child' || customerStatus == 'adult')) //check customer status
customerStatus = prompt('Error - enter \'child\' or \'adult\':');
deleteCustomer(customerName, customerStatus); //delete customer
}
function deleteCustomer(aName, aStatus) //delete customer
{
var newCustomerList = new Array(); //create new array
for (var i = 0; i < customerList.length; i++) //loop customers
{
var customer = customerList[i];
if ((customer.name != aName) || (customer.status != aStatus)) //check customer
{
var newIndex = newCustomerList.length; //add new user
newCustomerList[newIndex] = customer;
}
}
if (newCustomerList.length < customerList.length) //check deleted
{
alert('The customer has been deleted.');
}
else
{
alert('There are no customer to delete!');
}
customerList = newCustomerList; //update customer list
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<title>Coursework 2</title>
<script src="ZouYuncongINSTG018cw2.js" type="text/javascript"></script>
</head>
<body>
<div>
<button type="button" onclick="addCustomer();">Add Customer</button><br>
<button type="button" onclick="displayAllCustomers();">Display All Customers</button><br>
<button type="button" onclick="identifyThenDeleteCustomer();">Identify then Delete Customer</button>
</div>
</body>
</html>
You can make your delete function like this,
function deleteCustomer(aName, aStatus) //delete customer
{
for (var i = 0; i < customerList.length; i++) //loop customers
{
var customer = customerList[i];
if ((customer.name == aName) && (customer.status == aStatus)) //check customer
{
customerList = array.splice(i, 1);//delete from array itself
alert('The customer has been deleted.');
return;//stop
}
}
alert('There are no customer to delete!');
}
It will delete just one.
Since you said you cant use built in functions. In that case you have to copy the elements before and after the one to remove. You can have a control variable marking that you already found the one to delete. So no more deletions will happen.
For example,
function deleteCustomer(aName, aStatus) //delete customer
{
var onedeleted = false;
var newCustomerList = new Array(); //create new array
for (var i = 0; i < customerList.length; i++) //loop customers
{
var customer = customerList[i];
if ((customer.name != aName) || (customer.status != aStatus) || onedeleted) //check customer
{
var newIndex = newCustomerList.length; //add new user
newCustomerList[newIndex] = customer;
}
else
onedeleted = true;
}
if (newCustomerList.length < customerList.length) //check deleted
{
alert('The customer has been deleted.');
}
else
{
alert('There are no customer to delete!');
}
customerList = newCustomerList; //update customer list
}

Categories