I am currently in apprenticeship and I am having a problem.
I must be able to modify the quantity of the product or remove it from my basket. (therefore modify the localStorage)
But I cannot do it, I am aware that this question must have been asked several times.
But I can't find an answer to my problem among the many documentations, I must go about it wrong.
let basket = JSON.parse(localStorage.getItem("Sofas")) || [];
const cartItems = document.getElementById("cart__items");
contentBaskets = [];
function onQuantityChange(id) {
}
for (let i = 0; i < basket.length; i++) {
fetch("http://localhost:3000/api/products/" + basket[i].id)
.then((response) => response.json())
.then((data) => {
contentBaskets =
contentBaskets +
`<article class="cart__item" data-id=${basket[i].id}>
<div class="cart__item__img">
<img src=${data.imageUrl}>
</div>
<div class="cart__item__content">
<div class="cart__item__content__titlePrice">
<h2>${data.name}</h2>
<p>${data.price}€</p>
</div>
<div class="cart__item__content__settings">
<p>Couleur : ${basket[i].color}</p>
<div class="cart__item__content__settings__quantity">
<p>Qté : </p>
<input type="number" class="itemQuantity" name="itemQuantity" min="1" max="100" value=${basket[i].quantity} onchange=onQuantityChange('${basket[i].id}')>
</div>
<div class="cart__item__content__settings__delete">
<p class="deleteItem">Supprimer</p>
</div>
</div>
</div>
</article>`;
if (basket.length) {
cartItems.innerHTML = contentBaskets;
}
});
}
I'm not sure what's your question, but here's how to edit an object in localStorage.
// Get the string that's stored in localStorage
const stored = localStorage.getItem("sofas")
// Parse
const array = JSON.parse(stored) || []
// Push a new sofa to the array
array.push("IKEA Friheten")
// Set to localStorage the stringified version
// of the array, so you can get it later
localStorage.setItem("sofas", JSON.stringify(array))
Related
This is the code from telmo sampiao's shopping cart series, im missing remove items and increment/decrement buttons while also including it on local storage.
function displayCart(){
let cartItems = localStorage.getItem("productsInCart");
cartItems = JSON.parse(cartItems);
let productContainer = document.querySelector(".products");
let cartCost = localStorage.getItem('totalCost');
console.log(cartItems);
if( cartItems && productContainer){
productContainer.innerHTML = '';
Object.values(cartItems).map(item => {
productContainer.innerHTML += `
<div class="product">
<button class="btn btn-danger remove">Remove</button>
<img src="./img/${item.tag}.jpg">
<span>${item.name}</span>
</div>
<div class="price">
₱${item.price}.00
</div>
<div class="quantity"><i class="fa-solid fa-plus"></i> <span>${item.inCart}</span> <i class="fa-solid fa-minus"></i></div>
<div class="total">
₱${item.inCart * item.price}.00
</div>
`
});
productContainer.innerHTML += `
<div class="basketTotalContainer">
<h4 class="basketTotalTitle">
Cart Total
</h4>
<h4 class="basketTotal">
₱${cartCost}.00
</h4>
`;
}
}
Im not good at javascript I tried many diffrenet things but doesnt work
You only store one value for several different inputs. You need to identify each value for each input seperately.
HTML
Add a unique attribute "data-key". Or you can use the "id" of each element.
<div class="item">
<button class="plus" data-qty="1">+</button>
<input class="count" data-qty="1" type="number" min="1" max="5" value="1" data-key="myInput1"> <!-- add a unique key -->
<button class="minus" data-qty="1">-</button>
+
-
Jquery
I altered your code. See comments below. Now "data-key" is used as key for the localStorage.
<script>
let itemData = {
itemQty: 1
};
if (localStorage.getItem("itemData") === null) {
localStorage.setItem("itemData", JSON.stringify(itemData));
}
// new code for initializing
// parse all inputs and user their keys to find the corresponding itemdata
var allinputs = $('.count');
for (var i = 0; i < allinputs.length; i++) {
// get data according to "data-key"
var getItem = loadQuantity($(allinputs[i]).attr('data-key'));
if (getItem != null) {
$(allinputs[i]).val(getItem.itemQty);
} else {
// data not existing. Set global default value
saveQuantity(JSON.stringify(itemData), $(allinputs[i]).attr('data-key')); // *1 set first parameter just to itemData
}
}
$(".plus").click(function () {
// use key to get itemdata of this input
var keyOfInput = $(this).closest(".item").find(".count").attr('data-key');
var getItem = loadQuantity(keyOfInput);
getItem.itemQty = getItem.itemQty + 1;
saveQuantity(getItem, keyOfInput);
$(this).closest(".item").find(".count").val(getItem.itemQty);
});
$(".minus").click(function () {
// use key to get itemdata of this input
var keyOfInput = $(this).closest(".item").find(".count").attr('data-key');
var getItem = loadQuantity(keyOfInput);
if(getItem.itemQty != 1){
getItem.itemQty = getItem.itemQty - 1;
}
saveQuantity(getItem, keyOfInput);
$(this).closest(".item").find(".count").val(getItem.itemQty);
});
// added new parameter "key"
function saveQuantity(data, key) {
localStorage.setItem(key, JSON.stringify(data));
}
function loadQuantity(key) {
return JSON.parse(localStorage.getItem(key)); // *2 Change to JSON.parse(JSON.parse(localStorage.getItem(key)));
}
I am inserting the values of an input into an array of objects. Then, I want to get those values e show inside the HTML. Inserting each value inside the object is not the problem, every time I click the button, each value is successfully added. When I console.log() the array, it shows only one of each value added. The problem is when I try to show the content of the object inside the HTML element, it inserts all the data from the object over and over again, but I just want to add the last value added and keep what was previously inserted, not to add everything again.
What am I doing wrong?
This is my HTML
<main>
<div class="add-recipes">
<form id="form">
<h2>Add Recipe</h2>
<div class="input-wrapper">
<div class="text-input-wrapper">
<label for="title"
>Title
<input type="text" name="title" id="recipe-title" />
</label>
</div>
</div>
<button id="send-recipe-btn" type="submit">Send Recipe</button>
</form>
</div>
<div class="recipes-container"></div>
</main>
This is my JS File
let recipes = [];
const addRecipe = e => {
e.preventDefault();
let recipe = {
title: document.getElementById('recipe-title').value
};
recipes.push(recipe);
document.querySelector('form').reset();
recipes.forEach(e => {
const recipeContainer = document.querySelector('.recipes-container');
const recipeTitle = document.createElement('div');
recipeTitle.classList.add('recipe-title');
recipeContainer.append(recipeTitle);
recipeTitle.textContent = e.title;
});
console.log(recipes);
};
document.getElementById('send-recipe-btn').addEventListener('click', addRecipe);
Thanks for any tip or help to solve this.
Have the forEach()loop to start before recipeTitle.textContent = e.title;
let recipes = [];
const addRecipe = e => {
e.preventDefault();
let recipe = {
title: document.getElementById('recipe-title').value
};
recipes.push(recipe);
document.querySelector('form').reset();
const recipeContainer = document.querySelector('.recipes-container');
const recipeTitle = document.createElement('div');
recipeTitle.classList.add('recipe-title');
recipeContainer.append(recipeTitle);
recipes.forEach(e => {
recipeTitle.textContent = e.title;
});
console.log(recipes);
};
document.getElementById('send-recipe-btn').addEventListener('click', addRecipe);
In your event handler, you are looping over the recipes array and creating a new element every single time the button is pressed.
Just remove the loop and it will work properly
I think I know what the issue is, I suspect its this causing the issue?
let budgetArray = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "[]");
This is basically getting the stored data from here
/*----Store Stored budget list----*/
function storedEntry(){
const saveData = makeNewBudget();
const myJSON = JSON.stringify(saveData);
window.localStorage.setItem(STORAGE_KEY, myJSON);
}
The makenewbudget() is a function that contains an object of user input data
function makeNewBudget(){
const data = {
id: createId(),
cashflowNew: el.cashflow.value,
catagoryNew: el.catagory.value,
labelNew: el.label.value,
dateNew: createdDate(),
numberNew: el.number.value,
};
return data;
}
I have a function that when you click the create budget button its meant to add to the list
/*----form validation----*/
let budgetButton = document.querySelector(".budget-button");
let label = document.querySelector(".label");
let num = document.querySelector(".number");
let entry = document.querySelector(".entry")
budgetButton.addEventListener("click", () => {
if (!label.value || !num.value) {
alert("please make sure all inputs are filled");
}
budgetArray.push(makeNewBudget())
renderList();
storedEntry();
});
This is the renderList() function
/*----Render Budget List----*/
function renderList(){
el.list.innerHTML = budgetArray.map(function (data,i) {
return `<div class="entry">
<div class="list">
<button onclick="deleteItem(event, ${i})" class="Archive" data-id="${data.id}">
<img src="../resources/Images/archive.png" alt="Archive">
</button>
<button onclick="editItem(event, ${i})" class = "edit" data-id="${data.id}" class = "edit" data-id="${data.id}">
<img src="../resources/Images/edit.png" alt="Edit">
</button>
<div class="input" data-id="${data.id}"></div>
<label class="dateNew">${data.dateNew}</label>
<label class="cashflowNew">${data.cashflowNew}</label>
<label class="catagoryNew">${data.catagoryNew}</label>
<label class="labelNew">${data.labelNew}</label>
<label class="numberNew">${data.numberNew}</label>
</div>
</div>
<label class="total"></label>`;
});
}
I am not sure what I can do to fix the Uncaught TypeError: budgetArray.push is not a function
The error does not appear if I change
let budgetArray = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "[]");
to
let budgetArray = [];
So I am a bit stumped in how to fix that, because The localStorage.getItem needs to check the array for the stored data.
Im trying to upload multiple images, hence converting the image to a base64 encoded string and also storing its metadata with an array.We store the reference to the image path to database hence functionionality is written in backend for insertion.
However ,
To process image files into base64 and store metadata i use array and trying to pass as arguments to a function but i receive empty array in service call. Could someone help me understand why and how to fix this.
the upload image is called for every iteration of for loop , WHY?
Thanks in advance .
export class ItemsDetailsComponent {
//image variables
itemImageDetails: any = [];
ItemImageURLs: any = [];
itemImageCount: number = 0;
base64image: any = [];
CustImageData: any;
itemImageData: any;
itemimagePath: any;
fileList: any = [];
newImageMetaData: any = [];
imageMetaData: any = [];
addImagePopupVisible: boolean = false;
deleteImagePopupVisible: boolean = false;
tempImageCount: number = 0;
deleteImageURL: any;
deleteImageName: any;
deleteImageConfirmPopUp: boolean;
value: any[] = [];
constructor() {
// ...
}
processFile() {
let count = 0;
for (let i = 0; i < this.value.length;
(i++, count++)) {
this.fileList.push(this.value[count]);
this.httpDataService.getBase64(this.value[count])
.then(base64img => {
this.base64image[this.tempImageCount] = base64img;
this.base64image[this.tempImageCount] = this.base64image[this.tempImageCount].split(",")[1];
this.tempImageCount++;
this.newImageMetaData.push({
"type": this.fileList[i].type,
"name": this.fileList[i].name,
"size": this.fileList[i].size
});
});
}
//want to call this function only after for loop is complete but is getting called at every iteration , WHY?
this.uploadImages();
}
uploadImages() {
if (this.newImageMetaData.length == this.base64image.length) {
//recieves expected output(the array in log) **
console.log(this.newImageMetaData);
console.log(this.base64image); **
// below service call is receiving empty array - >> [] for ** [...this.base64image] ** ** [...this.newImageMetaData] **
this.httpDataService.uploadMultipleImages(["", this.itemCode, [...this.base64image],
[...this.newImageMetaData]
])
.subscribe(status => {
if ((status != -1) && status) {
this.toastr.success(status + "Image(s) Successfully Uploaded");
this.getImag();
this.getItemImageDetails();
this.newImageMetaData = [];
this.base64image = [];
} else {
this.toastr.error("Error Uploading image" + status + " Image(s) Uploaded ");
}
this.addImagePopupVisible = false;
});
}
}
//
<div class="widget-container">
<form enctype="multipart/form-data">
<dx-file-uploader #fileUploader [multiple]="true" accept="image/*" [(value)]="value" uploadMode="useForm"></dx-file-uploader>
<div class="content">
<div *ngIf="value.length > 0">
<h4>Selected Files</h4>
</div>
<div *ngFor="let file of value">
<div class="selected-item">
Name:
<span>{{file.name}}</span><br /> Size:
<span>{{file.size}}</span>bytes<br /> Type:
<span>{{file.type}}</span><br /> Last Modified Date:
<span>{{file.lastModifiedDate}}</span>
</div>
</div>
</div>
<dx-button text="Create Product" type="submit" (onClick)="uploadImages()">
</dx-button>
</form>
</div>
<div class="options">
<div class="caption">Options</div>
<div class="option">
<dx-check-box text="Allow multiple files selection" [(value)]="fileUploader.multiple"></dx-check-box>
</div>
</div>
Assuming that dx-button is a Call To Action, try and remove the action="uploadImages()" from the form tag, eventually, it will be called once processFile() completes the iteration.
If you keep an action as well as the submit button inside a form the button click will get performed.
OR
Remove onClick from button and replace uploadImages() with processFile() in form tag.
I am working on a wikipedia viewer (https://codepen.io/rwiens/pen/YLMwBa) which is almost done but I have 2 problems:
I cannot submit my search results when I press enter. I have added an event listener and can console.log "hello: but I cannot call the searchWiki function.
When I do a new search the results are appended to the bottom pf my old results.
I've searched the web for the last half day and am stuck. Any help would be appreciated.
<div class="container">
<div class="banner text-center align-items">
<h1>Wiki Search</h1>
<p>Search for articles on Wikipedia</p>
</div>
<form action="" class="text-center">
<input type="search" id="search-box" placeholder="Search Here">
<div class="buttons">
<input type="button" onclick="searchWiki()" id="search-
button" value="Search">
<input type="submit" value="Feel Lucky?">
</div>
</form>
<div class="articles">
<ul id="results">
</ul>
</div>
</div>
<script type="test/javascript">
const searchBox = document.getElementById('search-box');
const sButton = document.getElementById('search-button');
const results = document.getElementById('results');
window.onload = function() {
searchBox.focus();
};
const searchWiki = () => {
const keyword = searchBox.value;
fetch("https://en.wikipedia.org/w/api.php?
&origin=*&action=opensearch&search=" + keyword + "&limit=5", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({ query: event.currentTarget.value })
})
.then(response => response.json())
.then((data) => {
console.log(data);
build(data);
});
}
const build = (data) => {
let title = data[1];
let description = data[2];
let url = data[3];
for(let x = 0; x < 5; x++){
console.log(title);
const item = `<a href="${url[x]}" target="#">
<li>
<h5>${title[x]}</h5>
<p>${description[x]}.</p>
</li>
</a>`;
results.insertAdjacentHTML("beforeend", item);
}
}
searchBox.addEventListener("keyup", function(event) {
if (event.key === "Enter") {
searchWiki;
}
});
</script>
You are not calling searchWiki as function. Call it like this searchWiki();
Also you need to remove the form tag. Because you have button type elements in it , it is by default submitting your form on enter press.
Also clear results div before appending new data like this
results.innerHTML = ""
for(let x = 0; x < 5; x++){
console.log(title);
const item = `<a href="${url[x]}" target="#">
<li>
<h5>${title[x]}</h5>
<p>${description[x]}.</p>
</li>
</a>`;
results.insertAdjacentHTML("beforeend", item);
}
Check updated codepen
when I put searchWiki I am still not calling the search unfortunately. also, when i add results.innerHTML = "" my search only comes back with one result.
You need to add an event listener for the form submit. In that you need to cancel the event ( event.preventDefault() ).
Empty your results as #NanditaAroraSharma pointed out (best before calling build function)
Solved it. Removed the form as it was trying to send me to another page.
<div class="text-center">
<input type="search" id="search-box" placeholder="Search Here">
<div class="buttons">
<input type="button" onclick="searchWiki()" id="search-
button" value="Search">
<input type="button"
onclick="location.href='https://en.wikipedia.org/wiki/Special:Random';"
value="Feel Lucky?">
</div>
for building the html i took part of it out of the for loop.
const build = (data) => {
let title = data[1];
let description = data[2];
let url = data[3];
results.innerHTML = "";
for(let x = 0; x < 5; x++){
console.log(title);
const item = `<a href="${url[x]}" target="#">
<li>
<h5>${title[x]}</h5>
<p>${description[x]}.</p>
</li>
</a>`;
results.innerHTML += item;
}
}