How make Total cart without "location.reload();" - javascript

i have a problem
In my cart, i want to recalculta the amount total off quantity and price
without using
location.reload();
You can find here a bit of my code to understand how i created all my elements
let productLocalStorage = JSON.parse(localStorage.getItem("products"));
let cartItems = document.getElementById('cart__items');
/*This Function is here because of the unknown number of products in the cart **
**so i can reuse the creation of all elements if i need **
**All the JS elements have their own description to make the code more understandble*/
const cartProducts = (productStorage) => {
console.log(productStorage.product);
//------Create constant article who gonna contein all my elements------
let article = document.createElement('article');
article.classList.add('cart__item');
article.setAttribute( "data-id", productStorage.id);
let cartDivImg = document.createElement('div');
cartDivImg.classList.add('cart__item__img');
let cartImg = document.createElement('img');
cartImg.setAttribute('src', productStorage["imageUrl"]);
cartImg.setAttribute('alt', productStorage["alt"]);
let cartDivContent = document.createElement('div');
cartDivContent.classList.add('cart__item__content');
let cartDivContentTitle = document.createElement('div');
cartDivContentTitle.classList.add('cart__item__content__titlePrice');
let cartName = document.createElement('h2');
cartName.textContent = productStorage.name;
let cartColorName = document.createElement('h2');
cartColorName.textContent = productStorage.color;
let cartPrice = document.createElement('p');
cartPrice.textContent = productStorage.price + " €";
let cartDivSettings = document.createElement('div');
cartDivSettings.classList.add('cart__item__content__settings');
let cartDivQuantity = document.createElement('div');
cartDivQuantity.classList.add('cart__item__content__settings__quantity');
let cartQuantityP = document.createElement('p');
cartQuantityP.textContent = "Qté : ";
let cartQuantityInput = document.createElement('input');
cartQuantityInput.setAttribute("type","number");
cartQuantityInput.setAttribute("name","itemQuantity");
cartQuantityInput.classList.add('itemQuantity');
cartQuantityInput.setAttribute("min","1");
cartQuantityInput.setAttribute("max","100");
cartQuantityInput.setAttribute("value", productStorage.quantity);
let cartItemDelete = document.createElement('div');
cartItemDelete.classList.add('cart__item__content__settings__delete');
let CartDeleteP = document.createElement('p');
CartDeleteP.textContent = "Supprimer";
CartDeleteP.classList.add('deleteItem');
//Create all the elements
article.appendChild(cartDivImg);
cartDivImg.appendChild(cartImg);
article.appendChild(cartDivContent);
cartDivContent.appendChild(cartDivContentTitle);
cartDivContentTitle.appendChild(cartName);
cartDivContentTitle.appendChild(cartColorName);
cartDivContentTitle.appendChild(cartPrice);
cartDivContent.appendChild(cartDivSettings);
cartDivSettings.appendChild(cartDivQuantity);
cartDivQuantity.appendChild(cartQuantityP);
cartDivQuantity.appendChild(cartQuantityInput);
cartDivSettings.appendChild(cartItemDelete);
cartItemDelete.appendChild(CartDeleteP);
cartItems.appendChild(article);
}
if (productLocalStorage === null){
emptyCart();
}
// Loop "forEach" who create all the elements i need in my cart
else{
productLocalStorage.forEach(productLocalStorage => {
cartProducts(productLocalStorage);
});
}
let products = JSON.parse(localStorage.getItem("products"));
function removeItem() {
let removeBtn = document.querySelectorAll(".deleteItem");
for (let i = 0; i < removeBtn.length; i++) {
removeBtn[i].addEventListener("click", (event) => {
event.preventDefault();
let articleSupp = removeBtn[i].closest("article");
articleSupp.remove();
calculateTotal();
totalArtQte();
deleteItemSelected(i);
alert("This item will be delete from your cart !");
location.reload();
// Actualising the total amount of item in the cart
});
//This Function is here to remove my item in my local storage
function deleteItemSelected(index) {
products.splice(index, 1);
localStorage.setItem("products", JSON.stringify(products));
}
}
}
And here is my remove function
as you can see, i try to recall my calculateTotal() and my totalArtQte() function
to recalculate the amount total off quantity and price, but my function are only recall
if i use location.reload(); is it normal ? Do you know what can i do ?
I have to use only JavaScript
Thank you for those who gonna read / answer to my question

you don't have to call whole thing again or location.reload(). try to find the events when you want to re-calculate the cart. e.g. on
new item add
updated existing quantity
delete items
function getProductById(id) {
let index = productLocalStorage.findIndex( x => x.id == id );
return productLocalStorage[index];
}
// on new item
function addProduct(product) {
cartProducts(product);
productLocalStorage.push(product);
// update your cart total/whatever by looping through "productLocalStorage"
}
// on quantity change
cartQuantityInput.addEventListener('change', function($event) {
let product = getProductById(productStorage.id);
product.quantity = $event.target.value;
// update your cart total/whatever by looping through "productLocalStorage"
});
// on delete
let deleteButton = document.createElement('button');
deleteButton.innerHTML = 'Delete';
deleteButton.addEventListener('click', function deleteProductEvent($event) {
productLocalStorage = productLocalStorage.filter(function( product ) {
return product.id !== $event.target.parentElement.getAttribute('data-id');
});
this.removeEventListener('click', arguments.callee, false);
$event.target.parentElement.remove();
// update your cart total/whatever by looping through "productLocalStorage"
});
PS: make sure your UI, "productLocalStorage" variable and localstorage are in sync.
this will be much easier if you implement this with MVC/MVVM framework like Angular

Related

sum up user input with javascript

I'm trying to store a user input in a variable and output it.
I actually thought it would be very easy, but right now I'm stuck on this task
I'm trying to store this in an array. but I would also be happy if it was simply stored in a variable and I could output it.
I've been searching for it for a long time, but I have the feeling that I don't know exactly what to look for
here is my code:
let inputValuePrice = document.getElementById("myInput2").value;
let outputSumme = document.getElementById("summe");
outputSumme = parseFloat(inputValuePrice);
let sum = [];
sum.push(outputSumme);
console.log(sum);
<input type="number" id="myInput2" />
<input type="text" id="summe" />
edit:
I'm sorry. I'll explain it again in more detail. I want to add the number after each entry. It is a kind of to-do list with products and prices. each product is entered one by one along with the price. I would then like to add up the price of each product. In this case it is enough for me if it is first output in the console. If it is correct then I will let it output to the html.
if you need to calculate the sum of all inputs values as an integer or a float number it's very simple. you can use a simple function to sums all of your array elements like this:
let inputValuePrice = document.getElementById("myInput2").value;
let outputSumme = document.getElementById("summe");
outputSumme = parseFloat(inputValuePrice);
let sum = [];
sum.push(outputSumme);
console.log(getSumOfArray(sum));
function getSumOfArray(array){
let sumOfElements=0;
for (let i=0;i<array.length;i++){
sumOfElements=sumOfElements+array[i];
}
return sumOfElements;
}
If your array elements are all numbers you can use the reduce operator as follows:
const sumOfArray = sum.reduce((a, b) => a + b, 0)
Unfortunately I don't understand how it works. I have now the products with prices in the indexedDB in my code. There I wanted to read them out and sum them up again in an array. I'll send you the whole code. I would be very grateful for an explanation. what is wrong with my thinking? Here is my code.
This snippet is in a function that when run puts the products in a list in the HTML. The products are created in a foreach loop and in that I intercept the prices and send them outside of the function to another function which then has the data to calculate with. I hope it is understandable. I'll link the whole code at the end of this thread.
let products = makeTransaction('produkte', "readonly");
let request = products.getAll();
request.addEventListener('success', (event) => {
event.preventDefault();
document.querySelector('#product-list').innerHTML = "";
let data = event.target.result;
data.forEach((element) => {
/*-----------Elemente Kreieren------------*/
let li = document.createElement("li");
let edit = document.createElement('i');
let spanPrimary = document.createElement('span');
let inputLabel = document.createElement('label');
let productName = document.createElement('span');
let productPrice = document.createElement('span');
let spanSecondary = document.createElement('span');
let checkBox = document.createElement('input');
let closeBtn = document.createElement("span");
/*-----------Elemente einfügen------------*/
li.setAttribute('data-key', element.id);
productName.appendChild(document.createTextNode(element.title));
productPrice.appendChild(document.createTextNode(element.price + " €"));
spanPrimary.appendChild(productName);
spanPrimary.appendChild(productPrice);
inputLabel.appendChild(checkBox);
spanSecondary.appendChild(inputLabel);
li.appendChild(edit);
li.appendChild(spanPrimary);
li.appendChild(spanSecondary);
li.appendChild(closeBtn);
/*-----------Elemente klassifizieren------------*/
li.className = "mdl-list__item mdl-shadow--2dp";
edit.className = "material-symbols-outlined icon-edit-document";
edit.textContent = 'edit_document';
spanPrimary.className = "mdl-list__item-primary-content";
spanSecondary.className = "mdl-list__item-secondary-action";
inputLabel.className = "mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect";
productName.className = 'product-text';
productPrice.className = 'product-preis';
checkBox.className = "mdl-checkbox__input";
checkBox.setAttribute('id', 'my-id');
checkBox.setAttribute('type', 'checkbox');
closeBtn.className = "material-symbols-outlined hiding-list-item";
closeBtn.textContent = 'close';
componentHandler.upgradeElement(li);
let list = document.getElementById("product-list").appendChild(li);
// Füge die "edit" Funtion hinzu
let editieren = document.getElementsByClassName("icon-edit-document");
for (let i = 0; i < editieren.length; i++) {
editieren[i].onclick = function() {
showProducts(element.id);
}
}
// Füge die "close" Button Funktion hinzu
let close = document.getElementsByClassName("hiding-list-item");
for (let i = 0; i < close.length; i++) {
close[i].onclick = function() {
deleteProduct();
}
}
// Function for totalizing product prices
let produktPreis = element.price
sumPrice(produktPreis);
});
});
request.addEventListener('error', (event) => {
console.log(event.target.error);
});
}
and now the summation...
function sumPrice(produktPreis) {
produktPreis = parseFloat(produktPreis);
let arr = [];
arr.push(produktPreis);
console.log(getSum(arr));
console.log(sumOfArray);
function getSum(array) {
let sumOfElements = 0;
for (let i = 0; i < arr.length; i++) {
sumOfElements = sumOfElements + array[i];
}
return sumOfElements;
}
}
I've always been able to help myself. But I can't get any further with this supposedly simple thing.
and for the completeness. Here is my temporarily hosted website and Github. Thanks also for the previous replies.
Project site
https://liquefied-stripe.000webhostapp.com/
Github
https://github.com/StevoEs/Einkaufsliste/blob/main/main.js
Thanks!

why my JavaScript appendchild gives me an error when it to create list

im in my first week of java script coding so forgive me if this is simple question but i have been getting this error "Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at HTMLButtonElement.incrementCounter ". when I try to add li items in my ul this is the code.
const incrementBtn = document.querySelector('#increment')
const decrementBtn = document.querySelector('#decrement')
const counterEl = document.querySelector('#counter')
const ulElement = document.querySelector('#list-items')
let counter = 0
function incrementCounter() {
counter ++
counterEl.innerText = counter
// create element
const li = document.createElement('li')
const texNode = document.createTextNode('senntence '+ counter)
// append element
ulElement.appendChild('li')
}
function decrementCounter() {
counter --
counterEl.innerText = counter
}
incrementBtn.addEventListener('click', incrementCounter)
decrementBtn.addEventListener('click', decrementCounter)
the goal is li to be displayed when the increment button is clicked.
ill appreciate the help.
thank you.
You just mistyped your variable as a string
Here is the fixed code:
const incrementBtn = document.querySelector('#increment')
const decrementBtn = document.querySelector('#decrement')
const counterEl = document.querySelector('#counter')
const ulElement = document.querySelector('#list-items')
let counter = 0
function incrementCounter() {
counter ++
counterEl.innerText = counter
// create element
const li = document.createElement('li')
const texNode = document.createTextNode('senntence '+ counter)
// append element
ulElement.appendChild(li)
}
function decrementCounter() {
counter --
counterEl.innerText = counter
}
incrementBtn.addEventListener('click', incrementCounter)
decrementBtn.addEventListener('click', decrementCounter)

How to create a dynamic list, which removes deleted items from an array in JS?

I have created a list, which creates a new paragraph, with the value of the input field and adds the value of the input field into an array, if the add-Button is pressed. Each paragraph has a delete Button, which removes the paragraph visually, if pressed. Now I want that the Input of the paragraph also gets removed from the array.
For example lets say, that the array usernames includes usernames[1] = Lukas, usernames[2] = Martin, usernames[3] = Bob and I want to delete the paragraph, which includes Martin.
How can I create a function, where the paragraphs content also automatically gets removed from the array usernames. I would be very thankful for some help.
Here is my code:
let name = document.getElementById('name');
let addButton = document.getElementById('button');
let output = document.getElementById('output')
let usernames = [];
addButton.addEventListener('click', function() {
usernames.push(document.getElementById('name').value)
console.log(usernames)
let paragraph = document.createElement('ul')
paragraph.innerText = document.getElementById('name').value
output.appendChild(paragraph)
let deleteButton = document.createElement('button')
deleteButton.innerHTML = "X"
paragraph.appendChild(deleteButton)
deleteButton.addEventListener('click', function() {
output.removeChild(paragraph)
})
})
You can find an element in the array by name and remove it from there:
const usernameToRemove = usernames.indexOf(name => name === paragraph.innerText);
usernames.splice(usernameToRemove, 1);
let name = document.getElementById('name');
let addButton = document.getElementById('button');
let output = document.getElementById('output')
let usernames = [];
addButton.addEventListener('click', function() {
usernames.push(document.getElementById('name').value)
console.log(usernames)
let paragraph = document.createElement('ul')
paragraph.innerText = document.getElementById('name').value
output.appendChild(paragraph)
let deleteButton = document.createElement('button')
deleteButton.innerHTML = "X"
paragraph.appendChild(deleteButton)
deleteButton.addEventListener('click', function() {
const usernameToRemove = usernames.indexOf(name => name === paragraph.innerText);
usernames.splice(usernameToRemove, 1);
output.removeChild(paragraph)
})
})
<input id="name">
<button id="button">button</button>
<div id="output">output</div>
Every time the event handler to delete an item is called, just collect all of the text of each item and convert it into an array.
del.addEventListener('click', function() {
this.closest('li').remove();
usernames = [...list.querySelectorAll('li')].map(item => item.textContent);
console.log(usernames);
});
/*
This removes an <li>, if you don't change your "paragraph" then
change 'li' to 'ul'
*/
const user = document.getElementById('user');
const add = document.querySelector('.add');
const list = document.querySelector('.list')
let usernames = [];
add.addEventListener('click', function() {
let name = user.value;
user.value = '';
usernames.push(name);
console.log(usernames);
const item = document.createElement('li');
item.textContent = name+' ';
list.append(item);
const del = document.createElement('button');
del.textContent = "X";
item.append(del);
del.addEventListener('click', function() {
this.closest('li').remove();
usernames = [...list.querySelectorAll('li')].map(item => item.textContent);
console.log(usernames);
});
});
<input id='user'><button class='add'>ADD</button>
<ul class='list'></ul>
Thank you for your answers, but unfortunately the inner Text of the delete Button gets added to the array content, if something gets deleted, because it is part of the 'li' component. I simply created a div which includes the name and the delete Button to solve the problem. But nevertheless thank you for your help. Thats the working code:
const user = document.getElementById('user');
const add = document.querySelector('.add');
const list = document.querySelector('.list')
let usernames = [];
add.addEventListener('click', function() {
let name = user.value;
user.value = '';
usernames.push(name);
console.log(usernames);
const paragraph = document.createElement('div')
paragraph.style.display = 'flex'
const item = document.createElement('li');
item.textContent = name + ' ';
list.append(paragraph);
paragraph.append(item)
const del = document.createElement('button');
del.textContent = "X";
paragraph.append(del);
del.addEventListener('click', function() {
this.closest('div').remove();
usernames = [...list.querySelectorAll('li')].map(item => item.textContent);
console.log(usernames);
});
});

Want to delete the dynamically appended card from object array using splice method but the loop iteration is getting wrong values

I am making a task planner using classes.
These tasks are saved in the form of dynamically appended cards.
I am adding three cards in the array in class CardManager.
When I am selecting a card to delete by pressing a delete button the id is retrieved correctly, but in the last delfunc function which has a for loop, I am getting wrong array length.
So splice is not working.
The problem is in the loop of last function called delfunc().
class Card {
constructor(id, cname, pic, description, assignee, dDate, st) {
this.id = id;
this.cname = cname;
this.pic = pic;
this.description = description;
this.assignee = assignee;
this.dDate = dDate;
this.st = st;
// this.info=info;
}
}
class CardManager {
constructor() {
this.cardArr = [];
this.currentId = 1;
}
addcard(cname, pic, description, assignee, dDate, st) {
const nCard = new Card(this.currentId++, cname, pic, description, assignee, dDate, st); //creates
an instance of class card
this.cardArr.push(nCard);
}
}
const cardDeck = new CardManager(); //create an instance of card manager to access the members
// cardDeck.addcard("laundry","test","testing","Saeed","thursday","to do");
let tname = document.querySelector("#text1"); //accepting user input from form
let tdes = document.querySelector("#des");
let assignee = document.querySelector("#assignee");
let dDate = document.querySelector("#dDate");
let sTatus = document.querySelector("#stAtus");
let addButton = document.querySelector("#addButton");
addButton.onclick = function () {
alert("here i am card deck");
cardDeck.addcard(tname.value, "test", tdes.value, assignee.value, dDate.value, sTatus.value);
$('#myModal').modal('hide');
}
let btn1 = document.querySelector("#btn1");
let buttonCount = 1;
btn1.onclick = function displayListHtml() {
let html = "";
alert(cardDeck.cardArr.length);
for (let i = 0; i < cardDeck.cardArr.length; i++) {
html = `<div class="card">
<h1>${cardDeck.cardArr[i].cname}</h1>
<img src="sample.jpg" alt="Denim Jeans" style="width:100%">
<p>${cardDeck.cardArr[i].description}</p>
<p>${cardDeck.cardArr[i].assignee}</p>
<p>${cardDeck.cardArr[i].dDate}</p>
<p>${cardDeck.cardArr[i].st}</p>
<p>${cardDeck.cardArr[i].id}</p>
<p><button class="delete btn btn-primary" id="dbutton_${cardDeck.cardArr[i].id}">
Delete</button></p>
<p><button class="Edit btn btn-primary" id="ebutton_${cardDeck.cardArr[i].id}">
Edit</button></p>
</div>`;
buttonCount++;
}
const taskcontainer = document.querySelector("#taskcontainer");
const element = document.createRange().createContextualFragment(html);
element.querySelector("button.delete")
.addEventListener("click", delfunc);
element.querySelector("button.Edit")
.addEventListener("click", edifunc);
// element.addEventListener("click",yourClickEventHandler);
taskcontainer.append(element);
}
function delfunc() {
alert("i am in delete function");
const taskElement = event.target.closest(".delete"); //see line 74.
let delIdArr = taskElement.id.split("_"); //spliting the id by underscore. i.e . dbuton_id
let retreiveId = delIdArr[1];
for (let j = 0; j < this.cardDeck.cardArr.length; j++) {
if (retreiveId === j) {
this.cardDeck.cardArr.splice(retreiveId, 1);
}
}
}
Here is minimal version your concern. But looks like splice call doing as expected.
const del = (cardArr, retreiveId) => {
for (let j = 0; j < cardArr.length; j++) {
if (retreiveId === j) {
cardArr.splice(retreiveId, 1);
}
}
};
const cardArr = [2, 3, 4];
// delete the index 1
del(cardArr, 1);
console.log(cardArr);
// Case where delete index out of array index
const a = [1];
del(a, 1)
console.log(a);
function delfunc() {
alert("I am in delete function");
const taskElement = event.target.closest(".delete");//see line 74.
let delIdArr = taskElement.id.split("_");
let retrieveId = delIdArr[1];
var arr=[];
for (let j = 1; j <= cardDeck.cardArr.length; j++ ) {
if (retrieveId == j) {
arr = cardDeck.cardArr.splice(retreiveId, 1);
}

How to increment object property (isbn in this example) by one, each time I add some item to the list:?

I am trying to increment object property (isbn in this example) by one, each time I add some item to the list.
I want to each tr have unique isbn(1,2,3,4...)
I tried with newItem.isbn++, but each time I add item I get 1 (not 2,3,4...).
I am new to JavaScript and I really need some help here.
//Item Class
class Item {
constructor(isbn, item, amount, price) {
(this.isbn = isbn), (this.item = item), (this.amount = amount), (this.price = price);
}
}
//UI Class
class UI {
static displayItems() {
const storedItems = [
{
isbn: '1',
item: 'Some item',
amount: '2',
price: '$ 2500,00'
}
];
const items = storedItems;
items.forEach((item) => UI.addItemToList(item));
}
static addItemToList(item) {
const list = document.querySelector('tbody');
const row = document.createElement('tr');
row.innerHTML = `
<td>${item.isbn}</td>
<td>${item.item}</td>
<td>${item.amount}</td>
<td>${item.price}</td>
<td>
<i class="material-icons prefix grey-text text-darken-3">delete</i>
</td>
`;
list.appendChild(row);
}
static clearFields() {
document.querySelector('#item').value = '';
document.querySelector('#amount').value = '';
document.querySelector('#price').value = '';
}
}
//Event: Display Items
document.addEventListener('DOMContentLoaded', UI.displayItems);
//Event: Add Items
document.querySelector('form').addEventListener('submit', function(e) {
//Prevent default of submit
e.preventDefault();
//Get values from form
const isbn = 0;
const item = document.querySelector('#item').value;
const amount = document.querySelector('#amount').value;
const price = document.querySelector('#price').value;
//Instatiate Item
const newItem = new Item(isbn, item, amount, price);
newItem.isbn++; //Here I need help!!!!!!!
console.log(newItem);
//Add item to UI
UI.addItemToList(newItem);
//Clear input fields
UI.clearFields();
});
In this case, you would want your ISBN counter to be a global variable so that you may keep track of it through each iteration. Currently you are resetting it to zero every time you run that function since the variable is scoped to that function.
let isbn = 0;
// other code...
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
const item = document.querySelector('#item').value;
const amount = document.querySelector('#amount').value;
const price = document.querySelector('#price').value;
newISBN = isbn++; // notice here we are incrementing the global variable
const newItem = new Item(newISBN, item, amount, price); // here we are using this new incremented value to create your item
UI.clearFields();
});
Some stateful helper could be a solution. I.e.,
const createNewISBN = (initial = 0) => {
let isbn = initial;
return function newIsbn() {
isbn += 1;
return isbn;
}
}
const newIsbn = createNewIsbn(); // this will initiate new pool
Then later in your code:
document.querySelector('form').addEventListener('submit', function(e) {
//Prevent default of submit
e.preventDefault();
//Get values from form
const isbn = newIsbn(); // here no longer 0
const item = document.querySelector('#item').value;
const amount = document.querySelector('#amount').value;
const price = document.querySelector('#price').value;
//Instatiate Item
const newItem = new Item(isbn, item, amount, price);
// newItem.isbn++; //Here I need help!!!!!!! <-- this you don’t need anymore
console.log(newItem);
//Add item to UI
UI.addItemToList(newItem);
//Clear input fields
UI.clearFields();
});

Categories

Resources