'How can I store divs content into an array?
Hello this is my first post, i have been learning javascript for a week. I want to make a little app that calculate how much do you spend on subscription per month.
You can add a new subscription with the name and the subscription price with two inputs --> and it creates 2 new div(one is subscriptionName the other is subscriptionPrice) they are store into a new div (newSubscription).
Now i would like to store all the subscriptionPrice var into an array and addition all of them. (is it the right logic to apply ? maybe im wrong).
I also thought about doing the addition of the :
.abo-list > .abo:nth-child(1) > .abo-price
.abo-list > .abo:nth-child(1+1) > .abo-price
...
I have tried with this technic but the consol do not show even the first oneAboPrice.
var pricesValues = [];
for (var i = 0; i < oneAboPrice.length; i++) {
pricesValues.push(oneAboPrice[i].textContent);
}
console.log(pricesValues); /*dont show the values of every oneAboPrice*/
//Selectors
const nameInput = document.querySelector('.name');
const price = document.querySelector('.price');
const validate = document.querySelector('.validate');
const abosList = document.querySelector('.abo-list');
const montantTotal = document.querySelector('.montant-total');
//event listeners
validate.addEventListener('click', addAbo);
abosList.addEventListener('click', clickModify);
//functions
function addAbo(event){
event.preventDefault();
//creating the NewAbo DIV
const Abodiv = document.createElement('div');
Abodiv.classList.add('abo');
//creating a LI
const newAbo = document.createElement('li');
newAbo.innerText = nameInput.value + ' ' ;
newAbo.classList.add('abo-item');
Abodiv.appendChild(newAbo);
//creating a div Price of one Sub
const oneAboPrice = document.createElement('div');
oneAboPrice.classList.add('abo-price');
oneAboPrice.innerText = price.value;
Abodiv.appendChild(oneAboPrice);
//modify button
const modifyAbo = document.createElement('button');
modifyAbo.innerHTML = '<i class="fa-solid fa-pen"></i>';
modifyAbo.classList.add('modifyAbo');
Abodiv.appendChild(modifyAbo);
//trash button
const trashAbo = document.createElement('button');
trashAbo.innerHTML = '<i class="fa fa-trash"></i>';
trashAbo.classList.add("trashAbo");
Abodiv.appendChild(trashAbo);
//append to Abo-list
abosList.appendChild(Abodiv);
//total Amount of every newAboPrice
//reset input value
nameInput.value ="";
price.value="";
//store every .abo price (oneAboPrice)value into an array (this is where i need help)
var pricesValues = [];
for (var i = 0; i < oneAboPrice.length; i++) {
pricesValues.push(oneAboPrice[i].textContent);
}
console.log(pricesValues); /*dont show the values of every oneAboPrice*/
montantTotal.innerHTML = parseFloat(oneAboPrice.textContent); /* + oneAboPrice nth:child(2) + ....*/
}
function clickModify(e) {
const item = e.target;
//Delete newAbo
if(item.classList[0] === "trashAbo"){
const abo = item.parentElement;
abo.remove();
}
//modify newAbo (To do)
}
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Poppins&family=Saira+Extra+Condensed:wght@500&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.content-container{
display: flex;
justify-content: space-around;
}
.abo{
display: flex;
justify-content: space-between;
list-style-type: none;
}
.abo li{
flex: 1;
}
.fa-trash{
pointer-events: none;
}
.abo-price{
background: red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="style.css">
<title>Gestionnaire d'abonnements</title>
</head>
<body>
<div class="content-container">
<div class="left">
<p>Nom de l'abonnement</p><input type="text" class="name" placeholder="netflix">
<p>Prix mensuel</p><input type="number" class="price" placeholder="13,49">
<input type="button" value="Valide" class="validate">
</div>
<div class="right">
<h1>MES ABOS</h1>
<ul class="abo-list">
</ul>
<p class="montant-total"></p>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
Solution 1:[1]
I understand that you want to show the array of all items using this loop:
for (var i = 0; i < oneAboPrice.length; i++) {
pricesValues.push(oneAboPrice[i].textContent);
}
The problem is, oneAboPrice is not the all items that you want, it's a new element that you just created with this code:
//creating a div Price of one Sub
const oneAboPrice = document.createElement('div');
oneAboPrice.classList.add('abo-price');
oneAboPrice.innerText = price.value;
Abodiv.appendChild(oneAboPrice);
Solution
So, to correctly loop through all items, this is what the loop should be:
document.querySelectorAll('.abo-price').forEach(item => {
pricesValues.push(parseFloat(item.innerHTML));
});
Let's me explain. document.querySelectorAll('.abo-price') will select all of your oneAboPrice at the time being. Then you can use item.innerHTML to get the text inside of each item, not item.textContent.
//Selectors
const nameInput = document.querySelector('.name');
const price = document.querySelector('.price');
const validate = document.querySelector('.validate');
const abosList = document.querySelector('.abo-list');
const montantTotal = document.querySelector('.montant-total');
//event listeners
validate.addEventListener('click', addAbo);
abosList.addEventListener('click', clickModify);
//functions
function addAbo(event) {
event.preventDefault();
//creating the NewAbo DIV
const Abodiv = document.createElement('div');
Abodiv.classList.add('abo');
//creating a LI
const newAbo = document.createElement('li');
newAbo.innerText = nameInput.value + ' ';
newAbo.classList.add('abo-item');
Abodiv.appendChild(newAbo);
//creating a div Price of one Sub
const oneAboPrice = document.createElement('div');
oneAboPrice.classList.add('abo-price');
oneAboPrice.innerText = price.value;
Abodiv.appendChild(oneAboPrice);
//modify button
const modifyAbo = document.createElement('button');
modifyAbo.innerHTML = '<i class="fa-solid fa-pen"></i>';
modifyAbo.classList.add('modifyAbo');
Abodiv.appendChild(modifyAbo);
//trash button
const trashAbo = document.createElement('button');
trashAbo.innerHTML = '<i class="fa fa-trash"></i>';
trashAbo.classList.add("trashAbo");
Abodiv.appendChild(trashAbo);
//append to Abo-list
abosList.appendChild(Abodiv);
//total Amount of every newAboPrice
//reset input value
nameInput.value = "";
price.value = "";
//store every .abo price (oneAboPrice)value into an array (this is where i need help)
var pricesValues = [];
document.querySelectorAll('.abo-price').forEach(item => {
pricesValues.push(parseFloat(item.innerHTML));
});
console.log(pricesValues); /*dont show the values of every oneAboPrice*/
montantTotal.innerHTML = parseFloat(oneAboPrice.textContent); /* + oneAboPrice nth:child(2) + ....*/
}
function clickModify(e) {
const item = e.target;
//Delete newAbo
if (item.classList[0] === "trashAbo") {
const abo = item.parentElement;
abo.remove();
}
//modify newAbo (To do)
}
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Poppins&family=Saira+Extra+Condensed:wght@500&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.content-container {
display: flex;
justify-content: space-around;
}
.abo {
display: flex;
justify-content: space-between;
list-style-type: none;
}
.abo li {
flex: 1;
}
.fa-trash {
pointer-events: none;
}
.abo-price {
background: red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<link rel="stylesheet" href="style.css">
<title>Gestionnaire d'abonnements</title>
</head>
<body>
<div class="content-container">
<div class="left">
<p>Nom de l'abonnement</p><input type="text" class="name" placeholder="netflix">
<p>Prix mensuel</p><input type="number" class="price" placeholder="13,49">
<input type="button" value="Valide" class="validate">
</div>
<div class="right">
<h1>MES ABOS</h1>
<ul class="abo-list">
</ul>
<p class="montant-total"></p>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
Solution 2:[2]
If your only purpose is to get the total value of all subscriptions, you don't need an array. just call the function below every time a new subscription is added (call it inside addAbo).
// this will select all the `div` items with the class `.abo-price`
const subscriptionEls = document.querySelectorAll('.abo-price');
function calculateTotal() {
let total = 0;
// loop through each '.abo-price' element
subscriptionEls.forEach((el) => {
const textValue = el.innerText; // '12,49' (string)
const numericValue = parseInt(textValue); // 12,49 (number)
total += numericValue; // add each numerical value to the total
})
montantTotal.innerText = total;
}
Solution 3:[3]
Here is a complete version
I know it is a lot different from your code, but it is all recommended methods
//Selectors
const nameInput = document.querySelector('.name');
const price = document.querySelector('.price');
const validate = document.querySelector('.validate');
const abosList = document.querySelector('.abo-list');
const montantTotal = document.querySelector('.montant-total');
//event listeners
validate.addEventListener('click', addAbo);
abosList.addEventListener('click', clickModify);
let abos = []; // the main array
const render = () => {
let sum = 0;
abosList.innerHTML = abos.map(({name,price}) => { // grb the name and price from the object array
sum += price; // sum it for the montantTotal
// create an array of template literals
return `<div class="abo"><li>${name}</li><div class="abo-price">${price}</div>
<button type="button" class="modifyAbo"><i class="fa fa-pen"></i></button>
<button type="button" class="trashAbo"><i class="fa fa-trash"></i></button>
</div>`
}).join(""); // and join them with nothing
montantTotal.innerHTML = sum.toFixed(2)
}
function addAbo(event) {
event.preventDefault();
abos.push({ name: nameInput.value, price: +price.value }); // create an array of names,prices
//reset input value
nameInput.value = "";
price.value = "";
render(); // show the array
}
function clickModify(e) {
const item = e.target.closest('button');
//Delete newAbo
if (item.classList.contains("trashAbo")) {
const parent = item.closest('div')
const name = parent.querySelector('li').textContent; // save the name
parent.remove(); // before removing
abos = abos.filter(item => item.name != name); // remove the object with the name from the array
} else if (item.classList.contains("modifyAbo")) {
const parent = item.closest('div');
const aboName = parent.querySelector('li').textContent; // copy from the div
const aboPrice = +parent.querySelector('.abo-price').textContent; // copy from the div
nameInput.value = aboName; // set the form values
price.value = aboPrice; // so they can be edited
abos = abos.filter(item => item.name != aboName); // remove the abo so valide will add it back
}
render()
}
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Poppins&family=Saira+Extra+Condensed:wght@500&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.content-container {
display: flex;
justify-content: space-around;
}
.abo {
display: flex;
justify-content: space-between;
list-style-type: none;
}
.abo li {
flex: 1;
}
.fa-trash {
pointer-events: none;
}
.abo-price {
background: red;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<title>Gestionnaire d'abonnements</title>
<div class="content-container">
<div class="left">
<p>Nom de l'abonnement</p><input type="text" class="name" placeholder="netflix">
<p>Prix mensuel</p><input type="number" class="price" placeholder="13,49">
<input type="button" value="Valide" class="validate">
</div>
<div class="right">
<h1>MES ABOS</h1>
<ul class="abo-list">
</ul>
<p class="montant-total"></p>
</div>
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | phucbm |
| Solution 2 | Ammar Oker |
| Solution 3 |
