how to fix: Cannot read property 'value' of undefined - javascript

I am trying to get the value of the quantityElement so i can make the price change decrease/increase when the quantity goes down/up but i order for this to work i need to get the value of the quantityElement which keeps coming back as undefined in the console.
var removeCartitemButtons = document.getElementsByClassName('remove-btn')
console.log(removeCartitemButtons)
for (var i = 0; i < removeCartitemButtons.length; i++) {
var button = removeCartitemButtons[i]
button.addEventListener('click', function(event) {
console.log('clicked')
var buttonClicked = event.target
buttonClicked.parentElement.parentElement.remove()
updateCartTotal()
})
}
// Update Cart total price
function updateCartTotal() {
var cartItemContainer = document.getElementsByClassName('cart-items')[0]
var cartRows = cartItemContainer.getElementsByClassName('cart-info')
for (var i = 0; i < cartRows.length; i++) {
var cartRow = cartRows[i]
var priceElement = cartRow.getElementsByClassName('product-price')[0]
var quantityElement = cartRow.getElementsByClassName('quantity-value')
[0]
var price = parseFloat(priceElement.innerText.replace('R', ''))
var quantity = quantityElement.value
console.log(price * quantity)
}
}
<td>
<div class="cart-items">
<div class="cart-info">
<img src="images/men3(balenciaga).png" width="250px">
<span class="product-price">R7400</span>
</div>
<span class="cart-item-title">Balenciaga Speed High</span>
</div>
<br>
<button class="remove-btn" type="button">Remove</button>
</div>
</div>
</div>
</td>
<td><input class="quantity-value" type="number" value="1"></td>
</tr>

You are trying to get 'quantity-value' field inside cartRow, but it does not exist inside the 'cart-info' div, because of which you are getting this value as undefined.
var quantityElement = cartRow.getElementsByClassName('quantity-value')[0]
Your html should probably be like below:
var removeCartitemButtons = document.getElementsByClassName('remove-btn')
console.log(removeCartitemButtons)
for (var i = 0; i < removeCartitemButtons.length; i++) {
var button = removeCartitemButtons[i]
button.addEventListener('click', function(event) {
console.log('clicked')
var buttonClicked = event.target
buttonClicked.parentElement.remove()
// updateCartTotal()
})
}
<td>
<div class="cart-items">
<div class="cart-info">
<img src="images/men3(balenciaga).png" width="450px">
<span class="product-price">R7401</span>
<input class="quantity-value" type="number" value="1">
</div>
<span class="cart-item-title">Balenciaga Speed High1</span>
<button class="remove-btn" type="button">Remove1</button>
</div>
</td>
<td>
<div class="cart-items">
<div class="cart-info">
<img src="images/men3(balenciaga).png" width="450px">
<span class="product-price">R7402</span>
<input class="quantity-value" type="number" value="2">
</div>
<span class="cart-item-title">Balenciaga Speed High2</span>
<button class="remove-btn" type="button">Remove2</button>
</div>
</td>
<td>
<div class="cart-items">
<div class="cart-info">
<img src="images/men3(balenciaga).png" width="450px">
<span class="product-price">R7403</span>
<input class="quantity-value" type="number" value="3">
</div>
<span class="cart-item-title">Balenciaga Speed High3</span>
<button class="remove-btn" type="button">Remove3</button>
</div>
</td>

Related

How do I Multiply unit price and quantity for total price?

I have inputs like this -
<div id="multipleEntry">
<div class="d-flex">
<table class="table table-borderless">
<tbody>
<td>
<x-layouts.dropdowns name="product_id[]" title="Product" class="mt-2" id="productName" :dropItems="$products" :setItem="old('productName')" option1="Select Product" />
</td>
<td>
<x-layouts.input name="unitPrice[]" title="Unit Price" type="number" id="unitPrice" :value="111" />
</td>
<td>
<x-layouts.input name="quantity[]" title="Quantity" type="number" id="quantity" :value="old('quantity')" />
</td>
<td>
<x-layouts.input name="price[]" title="Price" type="number" id="price" :value="old('price')" />
</td>
</tbody>
</table>
</div>
</div>
<div class="col-sm-1 mb-3" id="controls">
<button class="btn btn-primary addNewBtn" type="button"><i class="fa-solid fa-plus"></i></button>
</div>
and for increment of columns I used -
const addNewBtn = document.querySelector(".addNewBtn");
const multipleEntry = document.querySelector("#multipleEntry");
addNewBtn.addEventListener("click", (e) => {
const lastRow = multipleEntry.lastElementChild;
let clone = lastRow.cloneNode(true);
multipleEntry.appendChild(clone);
});
I want to calculate the price and sub total price dynamically with javascript.
How do I do that?
I have modified your js function:
const addNewBtn = document.querySelector(".addNewBtn");
const multipleEntry = document.querySelector("#multipleEntry");
addNewBtn.addEventListener("click", (e) => {
let quantityArr = [];
let totalAmount = [];
const lastRow = multipleEntry.lastElementChild;
var length = document.getElementsByName('product_id[]').length;
var prices = document.getElementsByName('unitPrice[]');
var quantity = document.getElementsByName('quantity[]');
for (let i = 1; i <= length; i++) {
quantityArr.push(parseInt(quantity[i-1].value));
totalAmount.push(parseInt(quantity[i-1].value) * parseInt(prices[i-1].value));
}
console.log(totalAmount);
console.log(quantityArr);
let clone = lastRow.cloneNode(true);
multipleEntry.appendChild(clone);
});

JS Events - for loop

I'm creating a website database which will have roughly 80-100 cards of individual products in each one. Inside the cards there is a + and - button which changes an input element.
I have the counter code working fine but I need the buttons to be changing the input box in the card that is being pressed.
Is there any way to focus the click event so that it changes the input element inside it's div?
Should I be approaching this differently...
This is the complete card HTML:
<div class="card 688AttackSub">
<img src="688%20attach%20sub.jpg" alt="688 Attack Sub">
<div class="info-container">
<p>688 Attack Sub</p>
<p>1995</p>
<div class="no-sold">
<p>Number Sold</p>
<div class="buttons">
<button class="btn btn-outline-secondary btn-minus"><i class="fa fa-minus"></i></button>
<input class="form-control counter" min="0" name="quantity" value="1" type="number">
<button class="btn btn-outline-secondary btn-plus"><i class="fa fa-plus"></i></button>
</div>
</div>
<div class="sold-price">
<p>Total Sold Price</p>
<div class="buttons">
<button class="btn btn-outline-secondary btn-neg"><i class="fa fa-minus"></i></button>
<input class="form-control quantity counter-price" min="0" name="quantity" value="1" type="number">
<button class="btn btn-outline-secondary btn-add"><i class="fa fa-plus"></i></button>
</div>
</div>
<div class="av-price">
<p>Average Price</p><input class="form-control quantity avPrice" min="0" name="quantity" value="1" type="number">
</div>
<div class="last-sold">
<p>Last Sold Date</p><input class="form-control quantity lastSoldDate" min="0" name="quantity" value="1" type="number">
<p>Last Sold Price</p><input class="form-control quantity lastSoldPrice" min="0" name="quantity" value="1" type="number">
</div>
</div>
</div>
var buttonRed = document.querySelectorAll(".btn-minus");
var buttonPos = document.querySelectorAll(".btn-plus");
var buttonNeg = document.querySelectorAll(".btn-neg");
var buttonAdd = document.querySelectorAll(".btn-add");
var counter = document.querySelectorAll(".counter");
var counterPrice = document.querySelectorAll(".counter-price");
var averagePrice = document.querySelectorAll(".avPrice");
var lastSoldDate = document.querySelectorAll(".lastSoldDate");
var lastSoldPrice = document.querySelectorAll(".lastSoldPrice");
for (var i = 0; i < buttonRed.length; i++){
buttonRed[i].addEventListener("click", function() {
for (var m = 0; m < counter.length; m++){
counter[m].value = parseInt(counter[m].value) - 1;
} false;
} );}
for (var j = 0; j < buttonPos.length; j++){
buttonPos[j].addEventListener("click", function() {
for (var m = 0; m < counter.length; m++){
counter[m].value = parseInt(counter[m].value) + 1;
} false;
} );}
for (var k = 0; k < buttonNeg.length; k++){
buttonNeg[k].addEventListener("click", function() {
for (var n = 0; n < counterPrice.length; n++){
counterPrice[n].value = parseInt(counterPrice[n].value) - 1;
} false;
} );}
for (var l = 0; l < buttonAdd.length; l++){
buttonAdd[l].addEventListener("click", function() {
for (var n = 0; n < counterPrice.length; n++){
counterPrice[n].value = parseInt(counterPrice[n].value) + 1;
} false;
} );}
I ended up using Jquery as it has the $(this) input which will help with the 100 or so cards with identical class names
$(document).ready(function() {
$(".btn-minus").on('click', function(){
$(this).siblings($('.counter')).get(0).value--
});
});
$(document).ready(function() {
$(".btn-plus").on('click', function(){
$(this).prev($('.counter')).get(0).value++
});
});
$(document).ready(function() {
$(".btn-neg").on('click', function(){
$(this).siblings($('.counter-price')).get(0).value--
});
});
$(document).ready(function() {
$(".btn-add").on('click', function(){
$(this).prev($('.counter-price')).get(0).value++
});
});

JavaScript unsure how to get querySelectorAll() to connect to div class? [duplicate]

When I click on the checkbox at the top, it puts a '0' in the total box, so I know that it is connected correctly, however I think there is a problem in the logic in the loop. One of the elements in html looks like this.
const form = document.getElementById('bookingForm');
const total = document.getElementById('total');
const checkboxes = document.querySelectorAll('input[data-price][type=checkbox]');
const cbamount = checkboxes.length;
document.getElementsByName('event[]')[0].onclick = function() {
totalPrice()
};
function totalPrice() {
let totalprice = 0;
for (let i = 0; i < cbamount; i++) {
const box = checkboxes[i];
if (box.checked) {
box.dataset.price = totalprice + box.dataset.price;
} //if
} //for
document.getElementsByName("total")[0].value = totalprice;
}
<span class="eventTitle">Carmen </span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">T</span>
<span class="venueName">Mill </span>
<span class="eventPrice">3</span>
<span class="chosen"><input type="checkbox" name="event[]" value="11" data-price="35.00"></span>
<section id="Cost">
<h3>Total</h3>
Total <input type="text" name="total" size="20" readonly="">
</section>
You have no total in the code you provided.
I would personally use ID when only having one element and if more, use relative addressing and/or delegation
const form = document.getElementById('booking');
const total = document.getElementById('total');
document.getElementById("booking").addEventListener("click", function(e) {
if (e.target.name === "event[]") {
let totalprice = 0;
[...document.querySelectorAll('input[data-price][type=checkbox]')].forEach(function(box) {
if (box.checked) {
totalprice += +box.dataset.price;
} //if
})
document.querySelector("[name=total]").value = totalprice.toFixed(2);
}
})
<form id="booking" method="get">
<section id="book">
<h2>Select Events</h2>
<div class="item">
<span class="eventTitle">Carmen </span>
<span class="eventStartDate">2020</span>
<span class="eventEndDate">2020</span>
<span class="catDesc">T</span>
<span class="venueName">Mill </span>
<span class="eventPrice">3</span>
<span class="chosen"><input name="event[]" type="checkbox" value="11" data-price="35.00"></span>
</div>
<div class="item">
<span class="eventTitle">Ash</span>
<span class="eventStartDate">202</span>
<span class="eventEnd">2020-12-31</span>
<span class="catD">Exhib</span>
<span class="venueNa">The Biy</span>
<span class="eventPr">0.00</span>
<span class="chosen"><input type="checkbox" name="event[]" value="17" data-price="10.00"></span>
</div>
</section>
<section id="Cost">
<h3>Total</h3>
Total <input type="text" name="total" size="20" readonly="">
</section>
</form>

Get total price added up with jquery

Newbie on JS and got really stuck.
I have a plus and a minus button that adds up products. But I need that the result of this total price to adds up accordingly. And some of the products can only be bought with multiples of 2, 5 or 10.
I have here my html with 2 of my products. One that can only be sold with multiples of 5 and the other, multiple of 10.
<!-- Product #6 -->
<div class="item">
<div class="buttons">
<span class="delete-btn"></span>
<span class="like-btn"></span>
</div>
<div class="image">
<img src="intem-6.jpg" alt="" />
</div>
<div class="description">
<span>DLT-19 Heavy Blaster Rifle</span>
<span>Brown</span>
</div>
<div class="quantity">
<button class="plus-btn" type="button" name="button">
<img src="plus-btn.png" alt="" />
</button>
<input type="text" name="name" value="1">
<button class="minus-btn" type="button" name="button">
<img src="minus-btn.png" alt="" />
</button>
</div>
<div id="multiple5" class="total-price">$5800</div>
</div>
<!-- Product #7 -->
<div class="item">
<div class="buttons">
<span class="delete-btn"></span>
<span class="like-btn"></span>
</div>
<div class="image">
<img src="item-7.jpg" alt="" >
</div>
<div class="description">
<span>DL-44 Heavy Blaster Pistol</span>
<span>Brown</span>
</div>
<div class="quantity">
<button class="plus-btn" type="button" name="button">
<img src="plus-btn.png" alt="" />
</button>
<input type="text" name="name" value="1">
<button class="minus-btn" type="button" name="button">
<img src="minus-btn.png" alt="" />
</button>
</div>
<div id="multiple10" class="total-price">$1500</div>
</div>
</div>
And here is my jQuery that adds up 1 on.click of my buttons.
$('.minus-btn').on('click', function(e) {
e.preventDefault();
var $this = $(this);
var $input = $this.closest('div').find('input');
var value = parseInt($input.val());
if (value >= 1) {
value = value - 1;
} else {
value = 0;
}
$input.val(value);
});
$('.plus-btn').on('click', function(e) {
e.preventDefault();
var $this = $(this);
var $input = $this.closest('div').find('input');
var value = parseInt($input.val());
if (value < 100) {
value = value + 1;
} else {
value =100;
}
$input.val(value);
});
I tried doing separately along with my searches but couldn't implement this on my other code. Just want the result to add up and decrease the price along with the on.click event of my buttons.
<html>
<head>
<title>Hello</title>
<style>
*{
font-size: 25px;
}
</style>
</head>
<body>
<button id="plus"> + </button>
<input id="quantity" type="number" value='1'>
<button id="minus"> - </button>
<div id="total">5</div>
<script>
let plus = document.getElementById('plus');
let quantityEle = document.getElementById('quantity');
let minus = document.getElementById('minus');
let total = document.getElementById('total');
let quantity = quantityEle.value;
let price = 5;
plus.addEventListener('click', function(){
quantity++;
quantityEle.value = quantity;
total.innerHTML = price * quantity;
});
minus.addEventListener('click', function(){
if(quantity > 1)
quantity--;
quantityEle.value = quantity;
total.innerHTML = price * quantity;
});
quantityEle.addEventListener('change', function(){
quantity = quantityEle.value;
total.innerHTML = price * quantity;
});
var total = $this.closest('div').find('div');
</script>
</body>
</html>
Here you go!
$('.minus-btn').on('click', function(e) {
e.preventDefault();
var $parent = $(this).closest('.item');
var $input = $parent.find('input');
var $total = $parent.find('.total-price span');
var value = parseInt($input.val());
if (value >= 1) {
value = value - 1;
} else {
value = 0;
}
$input.val(value);
$total.html(value);
calcTotal();
});
$('.plus-btn').on('click', function(e) {
e.preventDefault();
var $parent = $(this).closest('.item');
var $input = $parent.find('input');
var $total = $parent.find('.total-price span');
var value = parseInt($input.val());
if (value < 100) {
value = value + 1;
} else {
value = 100;
}
$input.val(value);
$total.html(value);
calcTotal();
});
function calcTotal() {
let total = 0;
$(".total-price span").each(function() {
total += parseInt($(this).html());
});
$('#total').html('$' + total);
}
#total {
color: red;
}
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<!-- Product #6 -->
<div class="item">
<div class="buttons">
<span class="delete-btn"></span>
<span class="like-btn"></span>
</div>
<div class="image">
<img src="intem-6.jpg" alt="" />
</div>
<div class="description">
<span>DLT-19 Heavy Blaster Rifle</span>
<span>Brown</span>
</div>
<div class="quantity">
<button class="plus-btn" type="button" name="button">
<img src="plus-btn.png" alt="" /> +
</button>
<input type="text" name="name" value="1">
<button class="minus-btn" type="button" name="button">
<img src="minus-btn.png" alt="" /> -
</button>
</div>
<div id="multiple5" class="total-price">$<span>1</span></div>
</div>
<!-- Product #7 -->
<div class="item">
<div class="buttons">
<span class="delete-btn"></span>
<span class="like-btn"></span>
</div>
<div class="image">
<img src="item-7.jpg" alt="">
</div>
<div class="description">
<span>DL-44 Heavy Blaster Pistol</span>
<span>Brown</span>
</div>
<div class="quantity">
<button class="plus-btn" type="button" name="button">
<img src="plus-btn.png" alt="" /> +
</button>
<input type="text" name="name" value="1">
<button class="minus-btn" type="button" name="button">
<img src="minus-btn.png" alt="" /> -
</button>
</div>
<div id="multiple10" class="total-price">$<span>1</span></div>
</div>
<div>
Total: <span id="total">$2</span>
</div>
I think your question is really badly asked.
From what I understand, you seek to write an equivalence of jQuery in JS 'vanila' to increment decrement of (2, 5, 10) quantities and realize the corresponding totals.
so here is "my solution":
document
.querySelectorAll('button.minus')
.forEach(bt=>
{
bt.onclick=e=>
{
let P_parent = e.target.parentNode
, Inc = parseInt(P_parent.dataset.increment)
, U_price = parseFloat(P_parent.dataset.price).toFixed(2)
, val = parseInt(P_parent.querySelector('.quantity').value)
if (val > 0)
{
val -= Inc
P_parent.querySelector('.quantity').value = val
P_parent.querySelector('.total').textContent = '$ '+ (val * U_price).toFixed(2)
}
}
})
document
.querySelectorAll('button.plus')
.forEach(bt=>
{
bt.onclick=e=>
{
let P_parent = e.target.parentNode
, Inc = parseInt(P_parent.dataset.increment)
, U_price = parseFloat(P_parent.dataset.price).toFixed(2)
, Max = parseInt(P_parent.dataset.max)
, val = parseInt(P_parent.querySelector('.quantity').value)
if (val < Max)
{
val += Inc
P_parent.querySelector('.quantity').value = val
P_parent.querySelector('.total').textContent = '$ '+ (val * U_price).toFixed(2)
}
}
})
body { font: 14px sans-serif; padding: 1em; }
h3 { margin: 1.5em 0 0 0; }
input.quantity { width:4em; text-align: right }
.total { display: inline-block; width: 6em; text-align: right; font-weight: bold; border-bottom: 1px solid grey; margin-left: .5em }
p > button { font-weight: bold; }
<h3>by 2</h3>
<p data-increment="2" data-max=50 data-price="11">
<input class="quantity" type="text" value='0' readonly>
<button class="minus">-</button>
<button class="plus">+</button>
unit price : $11
<span class="total">$ 0</span>
</p>
<h3>by 5</h3>
<p data-increment="5" data-max=80 data-price="5.23">
<input class="quantity" type="text" value='0' readonly>
<button class="minus">-</button>
<button class="plus">+</button>
unit price : $5.23
<span class="total">$ 0</span>
</p>
<h3>by 10</h3>
<p data-increment="10" data-max=100 data-price="3.12">
<input class="quantity" type="text" value='0' readonly>
<button class="minus">-</button>
<button class="plus">+</button>
unit price : $3.12
<span class="total">$ 0</span>
</p>

Shopping Cart with JavaScript

I'm building a shopping cart with Vanilla JavaScript and i'm trying with Console.Log to show price of product "$19.99" when i click button to remove the product, but it's not showing nothing in Console.Log and i think problem is with html but i cannot find it, any idea?
<div class="click-cart">
<div class="cart-row">
<span class="cart-item cart-header cart-column">ITEM</span>
<span class="cart-price cart-header cart-column">PRICE</span>
<span class="cart-quantity cart-header cart-column">QUANTITY</span></div>
<div class="olp">
<div class="lakn">
<img class="shop-item-cart" src="https://cdn.thewirecutter.com/wp-content/uploads/2018/04/canon-dslrs-march-2018-2x1-lowres3496.jpg">
<span class="shop-title">Album 1</span>
<span class="shop-price">$19.99</span>
<input class="quantity-input" type="number" value="1">
<button class="delete-cart">X</button>
</div></div>
<div class="clear-checkout">
<button class="checkout">Checkout</button>
<button class="clear-cart">Clear Cart</button></div>
<div class="cart-items">
</div>
<div class="cart-total">
<strong class="cart-total-title">Total</strong>
<span class="cart-total-price">$10.79</span>
</div>
for (let i = 0; i < removeCartItemButtons.length; i++) {
let button = removeCartItemButtons[i]
button.addEventListener('click', function (event) {
let buttonCliked = event.target
buttonCliked.parentElement.parentElement.remove()
updateCartTotal ()
})
}
function updateCartTotal () {
let cartItemContainer = document.querySelector('.click-cart');
let cartRows = cartItemContainer.querySelector('.cart-row');
for (let i = 0; i < cartRows.length; i++) {
let cartRow = cartRows[i]
let priceElement = cartRow.querySelector('.shop-price');
let quantityElement = cartRow.querySelector('.quantity-input');
let price = priceElement.innerText
console.log(price)
}
}```
<div class="cart-row">
<span class="cart-item cart-header cart-column">ITEM</span>
<span class="cart-price cart-header cart-column">PRICE</span>
<span class="cart-quantity cart-header cart-column">QUANTITY</span>
</div>
The shop-price element is not in the cart-row div.
Furthermore, your for loop would not run because cartRows is not an array, instead it is a single HTMLElement with a length of undefined, use cartItemContainer.querySelectorAll('.cart-row') to get an interable NodeList instead.
Additionally, since you delete the element before you use the updateCartTotal function it is necessary to have a price variable preset to 0.
function updateCartTotal () {
let cartItemContainer = document.querySelector('.click-cart');
let cartRows = cartItemContainer.querySelectorAll('.cart-row');
let price = 0;
for (let i = 0; i < cartRows.length; i++) {
let cartRow = cartRows[i]
let priceElement = cartRow.querySelector('.shop-price');
let quantityElement = cartRow.querySelector('.quantity-input');
if (priceElement) {
price += Number(priceElement.innerText.replace('$',''));
}
console.log(price);
}
}

Categories