Tymeleaf Spring boot using javascript append html not woking click event - javascript

My Basket.js file
function test(){
let baskets = document.querySelectorAll('.basket');
baskets.forEach((basket) => {
$(basket).on("click",function(event){
console.log("clicked")
let productId;
let productName;
let productDiscount;
let productPrice;
let productImage;
let check = $(".gridDisable").attr("id");
if (check === "list") {
let parentDataSort = $(this).closest(".dateSort");
productId = parseInt(parentDataSort.find('.cartProduct').val())
productDiscount = $(this).closest(".dateSort").data("discount");
productName = parentDataSort.data("name");
productDiscount = parentDataSort.data("discount");
productPrice = productDiscount ? parentDataSort.find(".discountResult").data("result") : parentDataSort.data("price");
productImage = parentDataSort.find('.product-img-file').attr('src');
} else {
let parentDataColumn = $(this).closest(".dateSortColumn");
productId = parseInt(parentDataColumn.find('.cartProduct').val())
productDiscount = $(this).closest(".dateSortColumn").data("discount");
productName = parentDataColumn.data("name");
productDiscount = parentDataColumn.data("discount");
productPrice = productDiscount ? parentDataColumn.find(".discountResult").data("result") : parentDataColumn.data("price");
productImage = parentDataColumn.find('.product-image').attr('src');
}
addToBasket(productId, productName, productPrice, productImage);
})
})
}
test();
function addToBasket(productId, productName, productPrice, productImage) {
let cart = localStorage.getItem("cart");
let pCart = JSON.parse(cart) != null ? JSON.parse(cart) : [];
let present_or_not = pCart.findIndex(item => item.productId === productId);
if (cart == null || present_or_not == null || present_or_not === -1) {
let product = {
productId: productId,
productName: productName,
pPrice: productPrice,
quantity: 1,
image: productImage
};
pCart.push(product);
localStorage.setItem("cart", JSON.stringify(pCart));
} else {
let actual_stored_product = pCart[present_or_not];
pCart.splice(present_or_not, 1);
let actual_qty = actual_stored_product.quantity == null || actual_stored_product.quantity === "" ? 0 : actual_stored_product.quantity;
actual_stored_product.quantity = parseInt(actual_qty) + 1;
pCart.push(actual_stored_product);
localStorage.setItem("cart", JSON.stringify(pCart));
}
swal({
title: "Səbətə əlavə olundu",
icon: "success",
button: "Bağla",
});
let count = JSON.parse(localStorage.getItem("cart")).length;
$(".basket_count").text(count);
}
My active.js file
function showFilteredPriceProduct(min, max, isNew) {
$.get("/product/price?min=" + min + "&max=" + max + "&isNew=" + isNew, function (data) {
$("#column").empty();
$("#grid").empty();
if (data.data.length <= 10) {
$("#pagen").hide();
} else {
$("#pagen").show();
}
$.each(data.data, function (key, v) {
let item_content = `<div class="col-md-12 ml-4 my-3 py-2 dateSortColumn" data-name="${v.name}" data-price="${v.price}" data-discount="${v.isDiscount}">
${v.isNew ? `<div class="ribbon text-center" >Yeni<br></div>` : `<small style="display:none !important"></small>`}
${v.isDiscount ? `<div class="discount">- ${v.discount} %</div>` : `<small style="display:none !important"></small>`}
<div class="row bg-white">
<div class="col-md-3 mt-1">
<div class="container" id="wishlist">
<i class="far fa-heart js-heart heart"></i>
</div>
<img class="img-fluid img-responsive rounded product-image" src="${v.files[0].url}" />
</div>
<div class="col-md-6 mt-1">
<h5 class="detailLink">${v.name}</h5>
<div class="ratings-cart d-flex flex-row">
<div class="ratings mr-2">
<i class="fa fa-star"></i>
<i class="fa fa-star"></i>
<i class="fa fa-star"></i>
<i class="fa fa-star"></i>
</div>
</div>
</div>
<div class="align-items-center align-content-center col-md-3 border-left mt-1">
<label>
<input class="cartProduct" style="visibility: hidden!important;" th:value="${v.id}"
type="text">
</label>
<div class="d-flex flex-column justify-content-start">
${v.isDiscount ? `<div>
<h4 class="mr-1 product-price discountResult">${v.price - (v.price * v.discount / 100)}.00</h4>
</div>` : `<h4 class="mr-1 product-price">₼ ${v.price}.00</h4>`}
${v.isDiscount ? `<del>
<h4 style="font-size:14px;" class="mr-1 product-price">₼ ${v.price}.00</h4>
</del>` : `<small style="display:none;"></small>`}
</div>
<h6 class="text-success">Baxış sayı:<small class="productCount">${v.count}</small></h6>
<div class="d-flex flex-column mt-4">
<button class="btn btn-sm basket" type="button">Səbətə əlavə et</button>
</div>
</div>
</div>
</div>`
let grid_items = `<div class="col-12 col-sm-6 col-md-12 col-xl-6 dateSort" data-name="${v.name}" data-price="${v.price}">
<div class="single-product-wrapper">
${v.isNew ? `<div class="ribbon text-center" >Yeni<br></div>` : `<small style="display:none !important"></small>`}
${v.isDiscount ? `<div class="discount">- ${v.discount} %</div>` : `<small style="display:none !important"></small>`}
<div class="product-img">
<img alt="" class="product-img-file" src="${v.files[0].url}" />
</div>
<div class="product-description d-flex align-items-center justify-content-between">
<div class="product-meta-data">
<label>
<input class="cartProduct" style="visibility: hidden !important;" value="${v.id}" type="text" />
</label>
<div class="line"></div>
<div class="d-flex flex-column justify-content-start dataPrice">
${v.isDiscount ? `<div>
<p class="product-price discountResult"> ₼ ${v.price - (v.price * v.discount / 100)}.00 </p>
</div>` : ` <p class="product-price">₼ ${v.price}.00 </p>`}
${v.isDiscount ? `<del><h4 style="font-size:14px;" class="mr-1 product-price">₼ ${v.price}.00</h4>
</del>` : `<small style="display:none"></small>`}
</div>
<a href="/detail/${v.id}">
<h6 class="productName">${v.name}</h6>
</a>
<button class="basket" type="button">Səbətə əlavə et</button>
</div>
<div class="ratings-cart text-right">
<div class="ratings">
<i aria-hidden="true" class="fa fa-star"></i>
<i aria-hidden="true" class="fa fa-star"></i>
<i aria-hidden="true" class="fa fa-star"></i>
<i aria-hidden="true" class="fa fa-star"></i>
<i aria-hidden="true" class="fa fa-star"></i>
</div>
<small> Baxış sayı: <small>${v.count}</small> </small>
</div>
</div>
</div>
</div>
`
$("#grid").append(grid_items);
$("#column").append(item_content);
})
});
}
Hi everyone my simple project using thymeleaf and javascript code loading my project my add basket service normal working but sort change sort data returns spring boot backend service and append html code using javascript and jquery click event not working my add basket service

Related

How to update JavaScript after executing a function?

Good day to all, I'm new to js, so I would like to ask you, after executing the function, I add a response with content via innerHTML, but this content should also work with javascript, but it works, so I have to restart the page, how to do it right so that my functions work with the added answer?
Need to run this code
document.querySelectorAll('.btn-comment-like, .btn-comment-dislike').forEach((e) =>
e.addEventListener('click', function(e) {
e.preventDefault()
const commentRatingButtons = this;
const commentRatingId = commentRatingButtons.getAttribute('data-id');
const commentRatingAction = commentRatingButtons.getAttribute('data-action');
const commentTotalRating = document.querySelector(`button[data-comment-rating='${commentRatingId}']`);
const commentMessageRating = document.querySelector(`div[data-comment-message='${commentRatingId}']`);
fetch(`/api/comments/${commentRatingId}/${commentRatingAction}/`, {
method: 'POST',
headers: {
"X-CSRFToken": csrftoken,
"X-Requested-With": "XMLHttpRequest",
},
}).then((response) => response.json()).then((result) => {
if (result['error']) {
commentMessageRating.innerHTML = `
<div class="alert alert-danger rounded-0 shadow-sm me-2 align-self-start mb-2" role="alert" style="padding:2px;">
<i class="fa-solid fa-hexagon-exclamation"></i> ${result['error']}!
</div>`
} else {
if (commentRatingAction === 'like') {
commentMessageRating.innerHTML = `
<div class="alert alert-success rounded-0 shadow-sm me-2 align-self-start mb-2" role="alert" style="padding:2px;">
<i class="fa-solid fa-face-smile"></i> Спасибо за оценку, ${result['author']}!
</div>`
} else {
commentMessageRating.innerHTML = `
<div class="alert alert-danger rounded-0 shadow-sm me-2 align-self-start mb-2" role="alert" style="padding:2px;">
<i class="fa-solid fa-face-frown"></i> Спасибо за критику, ${result['author']}!
</div>`
}
commentTotalRating.innerHTML = `${result['comment_total_rating']} <i class="fa-solid fa-hand-holding-heart"></i>`
}
})
})
)
after doing this
commentForm.addEventListener('submit', function(e) {
e.preventDefault()
const commentForm = this;
const commentFormSubmit = commentForm.querySelector('#commentSubmit');
const commentArticleId = commentForm.getAttribute('data-article-id');
const commentEmpty = document.querySelector('#emptyComments');
const commentNestedList = document.querySelector('.nested-comments');
commentFormSubmit.innerText = "Ожидаем добавления...";
commentFormSubmit.disabled = true;
fetch(`/api/articles/${commentArticleId}/comments/create/`, {
method: 'POST',
headers: {
"X-CSRFToken": csrftoken,
"X-Requested-With": "XMLHttpRequest",
},
body: new FormData(commentForm),
}).then((response => response.json()))
.then((result) => {
if (result['comment_is_child']) {
const commentParentThread = document.querySelector(`#comment-thread-${result['comment_parent_id']}`);
commentParentThread.innerHTML += `
<ul id="comment-thread-${result['comment_id']}">
<li>
<div class="card mb-3 nth-shadow border-0 rounded-1">
<div class="card-body">
<div class="row">
<div class="col-md-2 d-none d-sm-inline pe-0">
<img src="${result['comment_avatar']}" class="img-fluid rounded-1 nth-img-comment nth-shadow" alt="{{ node.author.username }}">
</div>
<div class="col-md-10">
<div class="d-flex flex-row gap-2">
<div class="card-title">
<h6 class="nth-card-user-username mb-0">${result['comment_author']}</h6>
</div>
<div class="nth-card-title-username">
${result['comment_created_at']}
</div>
</div>
<div class="card-text mb-2">
${result['comment_content']}
</div>
<div class="d-grid gap-2 d-md-block">
<button class="btn btn-outline-secondary nth-btn-sm btn-like shadow-none" data-id="${result['comment_id']}" data-action="like" type="button">+1 <i class="fa-solid fa-heart-circle-plus"></i></button>
<button class="btn btn-outline-secondary nth-btn-sm btn-dislike shadow-none" data-id="${result['comment_id']}" data-action="dislike" type="button">-1 <i class="fa-solid fa-heart-circle-minus"></i></button>
<button class="btn btn-outline-secondary nth-btn-sm shadow-none" type="button" data-comment-rating="${result['comment_id']}">${result['comment_total_rating']} <i class="fa-solid fa-hand-holding-heart"></i></button>
</div>
</div>
</div>
</div>
</div>
</li>
</ul>
`
} else {
if (commentEmpty) {
commentEmpty.remove();
}
commentNestedList.innerHTML += `
<ul id="comment-thread-${result['comment_id']}">
<li>
<div class="card mb-3 nth-shadow border-0 rounded-1">
<div class="card-body">
<div class="row">
<div class="col-md-2 d-none d-sm-inline pe-0">
<img src="${result['comment_avatar']}" class="img-fluid rounded-1 nth-img-comment nth-shadow" alt="{{ node.author.username }}">
</div>
<div class="col-md-10">
<div class="d-flex flex-row gap-2">
<div class="card-title">
<h6 class="nth-card-user-username mb-0">${result['comment_author']}</h6>
</div>
<div class="nth-card-title-username">
${result['comment_created_at']}
</div>
</div>
<div class="card-text mb-2">
${result['comment_content']}
</div>
<div class="d-grid gap-2 d-md-block">
<button class="btn btn-outline-secondary nth-btn-sm btn-comment-like shadow-none" data-id="${result['comment_id']}" data-action="like" type="button">+1 <i class="fa-solid fa-heart-circle-plus"></i></button>
<button class="btn btn-outline-secondary nth-btn-sm btn-comment-dislike shadow-none" data-id="${result['comment_id']}" data-action="dislike" type="button">-1 <i class="fa-solid fa-heart-circle-minus"></i></button>
<button class="btn btn-outline-secondary nth-btn-sm shadow-none" type="button" data-comment-rating="${result['comment_id']}">${result['comment_total_rating']} <i class="fa-solid fa-hand-holding-heart"></i></button>
</div>
</div>
</div>
</div>
</div>
</li>
</ul>
`
}
commentForm.reset();
commentFormSubmit.innerText = "Добавить комментарий";
commentFormSubmit.disabled = false;
commentFormParentField.value = null;
})
})
I would be very grateful if you direct me to the correctness of creating such methods.
If you are feeling lazy to add it to the function then do something like:
let href = "http://"; //the location of your own html file you are working on.
//This will open your file on a new tab
window.open(href, "_blank");
//This will close your own tab.
window.close();
In this way you can close and open the tab again if it does'nt work with: "window.location.reload".
Put all your js code that you want to reload in a function and simply call it again when you want to. You can also use: window.location.reload();

Build shopping cart functions with vanilla Javascript

I am trying to build a shopping cart function.
I have a product page, that displays API data. When pressing the "Add to cart" button, the item should be added to local storage, and fetched from local storage to build the html content for the shopping cart.
The cart page should display this:
A list of all products added to the cart, each item must include a title, price, a link to the product view page and a product image.
If the cart is empty I want to display a message indicating this.
After the list of products, i want to display the total price of all the products in the cart.
Here is the combined code for the productDetail page and all cart functions that I have built so far.
import { baseUrl } from "../../constants/api.js";
import displayMessage from "../displayMessage.js";
// const productsURL = baseUrl + "/products";
const queryString = document.location.search;
const params = new URLSearchParams(queryString);
const id = params.get ("id");
let cartArray = [];
if(!id) {
document.location.href ="./index.html";
}
const productsUrl = baseUrl + "/products/" + id;
const results = await fetch(productsUrl);
const details = await results.json();
export async function productDetails() {
try {
// const response = await fetch(productUrl);
// const details = await response.json();
document.title = details.name;
const productContainer = document.querySelector(".product__card");
productContainer.innerHTML = `
<img src="${baseUrl + details.image.url}" class="card-img-top rounded-0 card__image" alt="${details.image.name}">
<div class="card-body p-0 pt-2 details">
<h2 class="">${details.title}</h2>
<div class="accordion" id="accordionExample">
<div class="card product__details">
<div class="details__header p-0 mt-2">
<p class="mb-0">
<button class="btn btn-link btn-block text-left p-0 m-0 text-decoration-none text-transform-none" type="button" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
<span class="padding__wrapper details__btn">Details</span>
<i class="fas fa-chevron-down"></i>
</button>
</p>
</div>
<div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordionExample">
<div class="card-body details__text">
${details.description}
</div>
</div>
</div>
</div>
<p class="card-text mt-2 details__price">
$${details.price}
</p>
<button class="btn btn-primary mt-3 shadow-none cart__button" data-product="${details.id}" type="button">
<span class="padding__wrapper">Add to cart</span>
<i class="fas fa-shopping-bag"></i>
</button>
</div>`;
const addCartButton = document.querySelectorAll("button.cart__button");
console.log(addCartButton);
addCartButton.forEach(function(button){
button.onclick = function(event) {
console.log(button);
cartArray.push(event.target.dataset.product);
console.log(cartArray);
// this line should look inside the function that loops the html and finds the item with the correct id
// const itemToAdd = details.find(item => item.id === event.target.dataset.product);
// console.log(itemToAdd);
// cartArray.push(itemToAdd);
// showCart(cartArray);
// localStorage.setItem("cartList", JSON.stringify(cartArray));
}
});
}catch(error) {
displayMessage("error", "Error when loading the product", ".product__card");
}
};
function showCart(cartItems) {
const cartContainer = document.querySelector(".cart__container");
const totalContainer = document.querySelector(".total__container");
cartContainer.innerHTML = "";
let total = 0;
cartItems.forEach(function (cartElement) {
total += cartElement.price;
cartContainer.innerHTML += `
<div class="row no-gutters">
<div class="loading"></div>
<div class="col-xs-4">
<img src="${baseUrl + cartElement.image.url}" class="card-img cart__product__image" alt="${cartElement.image.name}">
</div>
<div class="col-xs-8">
<div class="card-body">
<h5 class="card-title">${cartElement.title}</h5>
<p class="card-text">$${cartElement.price}</p>
<div class="row edit__amount">
<i class="fas fa-minus-circle"></i>
<div class=""></div>
<i class="fas fa-plus-circle"></i>
</div>
</div>
</div>
<div class="col-xs-4">
<i class="fas fa-trash-alt"></i>
</div>
</div>`;
})
totalContainer.innerHTML =
`<h2>Order Summary</h2>
<p>You order:</p>
<div class="table-responsive table-sm">
<table class="table">
<tr>
<td>Subtotal:</td>
<td>$${total}</td>
</tr>
<tr>
<td>Shipping:</td>
<td>Free Shipping</td>
</tr>
</table>
</div>
<hr/>
<div class="table-responsive table-sm">
<table class="table">
<tr>
<td>Total:</td>
<td>$${total}</td>
</tr>
</table>
</div>
To Checkout`;
};

How do i add items to my cart using javascript?

When I click on a product in the store section I want it to go in the cart. For some reason nothing is showing up in the cart but empty space. `//show cart
(function(){
const cartInfo = document.getElementById('cart-info');
const cart = document.getElementById('cart');
cartInfo.addEventListener('click', function(){
cart.classList.toggle('show-cart')
})
})();
//add items to cart
(function() {
const cartBtn = document.querySelectorAll('.store-item-icon');
cartBtn.forEach(function(btn) {
btn.addEventListener('click', function(event) {
if (event.target.parentElement.classList.contains('store-item-icon'))
{
let fullPath =
event.target.parentElement.previousElementSibling.src;
let pos = fullPath.indexOf('img') + 3;
let partPath = fullPath.slice(pos);
const item = {};
item.img = `
img - cart$ {
partPath
}
`;
let name =
event.target.parentElement.parentElement.nextElementSibling
.children[0].children[0].textContent;
item.name = name;
let price =
event.target.parentElement.parentElement.nextElementSibling
.children[0].children[1].textContent;
let finalPrice = price.slice(1).trim();
item.price = finalPrice;
console.log(finalPrice);
console.log(item);
const cartItem = document.createElement('div')
cartItem.classList.add('cart-item', 'd-flex', 'justify-content-between',
'text-capitalize', 'my-3');
cartItem.innerHtML = ` < img
src = "${item.img}"
class = "img-fluid rounded-circle"
id = "item-img"
alt = "" /
>
<
div class = "item-text" >
<
p id = "cart-item-title"
class = "font-weight-bold mb-0" >
$ {
item.name
} <
/p> <
span > £ < /span> <
span id = "cart-item-price"
class = "cart-item-price mb-0" >
$ {
item.price
} < /span >
<
/div> <
a href = "#"
id = "cart-item-remove"
class = "cart-item-remove" >
<
i class = "fas fa-trash" > < /i> <
/a> <
/div> *
/
`;
//select cart
const cart = document.getElementById('cart');
const total = document.querySelector('.cart-total-container');
cart.insertBefore(cartItem, total);
alert('item added to the cart')
}
});
});
})();
<!--cart-->
<div class="cart" id="cart">
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon2.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--total-->
<div class="cart-total-container d-flex justify-content-around text-capitalize mt-5">
<h5>total</h5>
<h5>£ <strong id="cart-total" class="font-weight-bold">21.99</strong></h5>
</div>
<!--end of total-->
<!--buttons-->
<div class="cart-buttons-container mt-3 d-flex justify-content-between">
clear cart
checkout
</div>
</div>
</div>
</div>
<!--store items-->
<div class="row store-items" id="store-items">
<!-- single item-->
<div class="col-10 col-sm-6 col-lg-4 mx-auto my-3 store-item sweets" data-item="sweets">
<div class="card single-item">
<div class="img-container">
<img src="img/bodybutter.jpg" class="card-img-top store-img" />
<span class="store-item-icon"><i class="fas fa-shopping-cart"></i> </span>
</div>
<div class="card-body">
<div class="card-text d-flex justify-content-between text-capitalize">
<h5 id="store-item-name">body butter</h5>
<h5 class="store-item-value">£ <strong id="store-item-price" class="font-weight-bold">10.99</strong></h5>
</div>
</div>
</div>
</div>
<!--singles item end -->
There are more then one errors in your code starting with innerHtML instead of innerHTML and incorrectly formatted template literal and incorrect bindings inside it ... so I have decided to just post a working code. Keep in mind that incorrect HTML will be treated as text only, so check the correctness of the HTML block you want to place inside innerHTML, because there was as an extra closing div also.
(function(){
const cartInfo = document.getElementById('cart-info');
const cart = document.getElementById('cart');
cartInfo.addEventListener('click', function(){
cart.classList.toggle('show-cart')
})
})();
//add items to cart
(function() {
const cartBtn = document.querySelectorAll('.store-item-icon');
cartBtn.forEach(function(btn) {
btn.addEventListener('click', function(event) {
if (event.target.parentElement.classList.contains('store-item-icon'))
{
let fullPath =
event.target.parentElement.previousElementSibling.src;
let pos = fullPath.indexOf('img') + 3;
let partPath = fullPath.slice(pos);
const item = {};
item.img = `img - cart${partPath}`;
let name = event.target.parentElement.parentElement.nextElementSibling
.children[0].children[0].textContent;
item.name = name;
let price =
event.target.parentElement.parentElement.nextElementSibling
.children[0].children[1].textContent;
let finalPrice = price.slice(1).trim();
item.price = finalPrice;
console.log(finalPrice);
console.log(item);
const cartItem = document.createElement('div')
cartItem.classList.add('cart-item', 'd-flex', 'justify-content-between', 'text-capitalize', 'my-3');
cartItem.innerHTML =
`<img src = "${item.img}" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">${item.name}</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">${item.price}</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i></a>`;
//select cart
const cart = document.getElementById('cart');
const total = document.querySelector('.cart-total-container');
cart.insertBefore(cartItem, total);
alert('item added to the cart')
}
});
});
})();
.cart.show-cart{display:block}
.cart{display:none; border: 1px solid #000; padding: 20px}
.store-items{margin:20px 0;border:1px solid #000;padding: 20px}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta2/css/all.min.css" integrity="sha512-YWzhKL2whUzgiheMoBFwW8CKV4qpHQAEuvilg9FAn5VJUDwKZZxkJNuGM4XkWuk94WCrrwslk8yWNGmY1EduTA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<a id="cart-info" href="javascript:;">Toggle Cart</a>
<!--cart-->
<div class="cart" id="cart">
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--cart item-->
<div class="cart-item d-flex justify-content-between text-capitalize my-3">
<img src="img-cart/creamicon2.jpg" class="img-fluid rounded-circle" id="item-img" alt="" />
<div class="item-text">
<p id="cart-item-title" class="font-weight-bold mb-0">cart item</p>
<span>£ </span>
<span id="cart-item-price" class="cart-item-price mb-0">10.99</span>
</div>
<a href="#" id="cart-item-remove" class="cart-item-remove">
<i class="fas fa-trash"></i>
</a>
</div>
<!--cart item end-->
<!--total-->
<div class="cart-total-container d-flex justify-content-around text-capitalize mt-5">
<h5>total</h5>
<h5>£ <strong id="cart-total" class="font-weight-bold">21.99</strong></h5>
</div>
<!--end of total-->
<!--buttons-->
<div class="cart-buttons-container mt-3 d-flex justify-content-between">
clear cart
checkout
</div>
</div>
</div>
</div>
<!--store items-->
<div class="row store-items" id="store-items">
<!-- single item-->
<div class="col-10 col-sm-6 col-lg-4 mx-auto my-3 store-item sweets" data-item="sweets">
<div class="card single-item">
<div class="img-container">
<img src="img/bodybutter.jpg" class="card-img-top store-img" />
<span class="store-item-icon"><i class="fas fa-shopping-cart"></i></span>
</div>
<div class="card-body">
<div class="card-text d-flex justify-content-between text-capitalize">
<h5 id="store-item-name">body butter</h5>
<h5 class="store-item-value">£ <strong id="store-item-price" class="font-weight-bold">10.99</strong></h5>
</div>
</div>
</div>
</div>
<!--singles item end -->

AngularJS application: unable to update $index

I am working on an app in AngularJS 1.6, using the Giphy.com api.
There is a Plunker HERE.
I iterate over an array of "giphys"coming from https://api.giphy.com/v1/gifs/trending?api_key=myApyKey and display them into Bootstrap 4 cards.
There is a view single giphy functionality. In the controller I have:
// Create controller for the "giphyApp" module
app.controller("giphyCtrl", ["$scope", "$http", "$filter", "$timeout", function($scope, $http, $filter, $timeout) {
var url = "https://api.giphy.com/v1/gifs/trending?api_key=PTZrBlrq8h2KUsRMeBuExZ5nHyn7dzS0&limit=120&rating=G";
$scope.giphyList = [];
$scope.search = "";
$scope.filterList = function() {
var oldList = $scope.giphyList || [];
$scope.giphyList = $filter('filter')($scope.giphys, $scope.search);
if (oldList.length != 0) {
$scope.pageNum = 1;
$scope.startAt = 0;
};
$scope.itemsCount = $scope.giphyList.length;
$scope.pageMax = Math.ceil($scope.itemsCount / $scope.perPage);
};
$http.get(url)
.then(function(data) {
// giphy arary
$scope.giphys = data.data.data;
$scope.filterList();
console.log($scope.giphys);
// Paginate
$scope.pageNum = 1;
$scope.perPage = 24;
$scope.startAt = 0;
$scope.filterList();
$scope.currentPage = function(index) {
$("html, body").animate({
scrollTop: 0
}, 500);
$timeout( function(){
$scope.pageNum = index + 1;
$scope.startAt = index * $scope.perPage;
},0);
};
$scope.prevPage = function() {
if ($scope.pageNum > 1) {
$scope.pageNum = $scope.pageNum - 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
$scope.nextPage = function() {
if ($scope.pageNum < $scope.pageMax) {
$scope.pageNum = $scope.pageNum + 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
$scope.selectedIndex = null;
$scope.selectedGiphy = null;
$scope.fetchSinglegGiphy = function(giphy, index) {
console.log(index);
$scope.selectedIndex = index;
$scope.selectedGiphy = giphy;
}
});
}]);
The Grid
<div class="row grid" ng-if="giphyList.length > 0">
<div data-ng-repeat="giphy in giphyList | limitTo : perPage : startAt"
class="col-xs-12 col-sm-6 col-lg-4 col-xl-3 d-flex mb-4">
<div class="giphy d-flex flex-column w-100">
<div class="thumbnail pb-2 text-center" data-toggle="modal"
data-target="#giphyModal"
ng-click="fetchSinglegGiphy(giphy, $index)">
<img ng-src="{{giphy.images.downsized.url}}" class="img-fluid">
</div>
<div class="text mt-auto">
<p class="m-0 meta">{{giphy.import_datetime | dateParse | date : "MMMM dd y" }}</p>
<p class="rating m-0">
<i class="fa fa-star" aria-hidden="true"></i> {{giphy.rating | capitalize}}
</p>
<ul class="list-unstyled mb-0 text-center">
<li ng-if="giphy.username != ''" class="text-muted">{{giphy.type | capitalize}} file uploaded by
<br><strong>{{giphy.username | capitalize }}</strong>
</li>
<li ng-if="giphy.username == ''" class="text-muted">{{giphy.type | capitalize}} file uploaded by
<br> <strong>Unknown</strong>
</li>
<li class="h6">{{giphy.title | titlecase }}</li>
</ul>
</div>
</div>
</div>
</div>
The Modal
<div class="modal fade" id="giphyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title h-3">{{selectedGiphy.title | titlecase }}</h4>
<button type="button" class="close" data-dismiss="modal">
<span>×</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="image image text-center">
<img ng-src="{{selectedGiphy.images.original.url}}"
alt="{{selectedGiphy.title }}" class="img-fluid">
</div>
</div>
</div>
</div>
<div class="modal-footer justify-content-between">
<div class="text-muted">Image ID: {{selectedGiphy.id}}</div>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-success" data-dismiss="modal">
<i class="fa fa-times-circle"></i> Close
</button>
</div>
</div>
</div>
</div>
</div>
This part of the application works fine.
I had expected to be able to easily add a next and previous giphy to the modal above:
<div class="controls text-center">
<a href="#" ng-click="fetchSinglegGiphy(giphy, $index = $index - 1)" class="left">
<i class="fa fa-chevron-left"></i>
</a>
<a href="#" ng-click="fetchSinglegGiphy(giphy, $index = $index + 1)" class="right">
<i class="fa fa-chevron-right"></i>
</a>
</div>
To my surprise this does not work. When I click any one of the controls, the GIF file remains the same, wile all the text in the modal disappears.
Questions:
What is wrong with this approach?
Do you see a viable alternative?
index.html
<div class="modal fade" id="giphyModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="controls text-center">
<i class="fa fa-chevron-left"></i>
<i class="fa fa-chevron-right"></i>
</div>
<div class="modal-header">
<h4 class="modal-title h-3">
{{ selectedGiphy.title | capitalize }}
</h4>
<button type="button" class="close" data-dismiss="modal">
<span>×</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-12">
<div class="image image text-center">
<img ng-src="{{ selectedGiphy.images.original.url }}" alt="{{ selectedGiphy.title }}" class="img-fluid" image-on-load ng-hide="modalImageLoading" />
<div class="spinner-border" ng-if="modalImageLoading"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer justify-content-between">
<div class="text-muted">
Image ID: {{ selectedGiphy.id }}
</div>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-success" data-dismiss="modal">
<i class="fa fa-times-circle"></i> Close
</button>
</div>
</div>
</div>
</div>
</div>
MODIFICATIONS:
<i class="fa fa-chevron-left"></i>
<i class="fa fa-chevron-right"></i>
fetchSinglegGiphyModal handles both previous and next Giphy based on the condition that acts on the argument prev or next value that we pass in the function.
I have also added the following code to introduce loader which comes with bootstrap to indicate that GIF image is being loaded in the background.
<div class="image image text-center">
<img ng-src="{{ selectedGiphy.images.original.url }}" alt="{{ selectedGiphy.title }}" class="img-fluid" image-on-load ng-hide="modalImageLoading" />
<div class="spinner-border" ng-if="modalImageLoading"></div>
</div>
app.js
$scope.modalImageLoading = false;
$scope.fetchSinglegGiphy = function (giphy, index) {
$scope.selectedIndex = index;
$scope.selectedGiphy = giphy;
$scope.modalImageLoading = true;
};
$scope.fetchSinglegGiphyModal = function (dir) {
let selectedGiphy = null;
if (dir === "prev") $scope.selectedIndex -= 1; // To load previous
else if (dir === "next") $scope.selectedIndex += 1; // To load next
selectedGiphy = $scope.giphyList[$scope.selectedIndex];
if (selectedGiphy) {
$scope.selectedGiphy = selectedGiphy;
$scope.modalImageLoading = true;
}
};
$scope.fetchSinglegGiphyModal acts on the condition we pass in the parameter and shows the corresponding Giphy data.
I have implemented a custom directive to show the image element and hide the loader when the image is downloaded. Here is the directive code:
app.directive('imageOnLoad', function () {
return {
restrict: 'A',
controller: 'giphyCtrl',
link: function (scope, element, attrs) {
element.bind('load', function () {
scope.$apply(function () {
scope.modalImageLoading = false;
});
});
}
}
});
Here is the modified plunker code.
Hope it helps!
When I click any one of the controls, the GIF file remains the same
Check to see if giphy equals what you expect:
$scope.fetchSinglegGiphy = function(giphy, index) {
$scope.selectedIndex = index;
$scope.selectedGiphy = giphy;
if ( giphy != $scope.giphyList[index] ) {
$scope.selectedGiphy = $scope.giphyList[index];
};
};
Update the selectedGiphy in the case that it is not.
You not only use $index outside of the ng-repeat block, but also you use giphy outside of that block, where it is not defined.
I assume you have $scope.giphyList defined in your controller. So all you have to do is to send the index.
$scope.selectedIndex = null;
$scope.selectedGiphy = null;
$scope.fetchSinglegGiphy = function(index) {
$scope.selectedIndex = index;
$scope.selectedGiphy = $scope.giphyList[index];
}
<div class="controls text-center">
<a href="#" ng-click="fetchSinglegGiphy(selectedIndex-1)" class="left">
<i class="fa fa-chevron-left"></i>
</a>
<a href="#" ng-click="fetchSinglegGiphy(selectedIndex+1)" class="right">
<i class="fa fa-chevron-right"></i>
</a>
</div>
I hope this helps,
Cheers
Where you move the giphy to the modal, you should also send the $index (as you really did), so in the modal you know who your index is, regardless of $index.
<div class="controls text-center">
<i class="fa fa-chevron-left"></i>
<i class="fa fa-chevron-right"></i>
</div>

My question is about getting a solution to calculate the total price of an order with javascript

I'm developping a web page were there is some products in their prices and the quantity of each one, what I'm trying to do, is to calculate the total price, but, with the same class name for every product
I've already tried the solution in the code bellow, but I'm not getting the right price
<ul class="list-group list-group-flush">
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_newyork_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">New York City</p>
<p class="font-italic">Quantité : <span class="qte">1</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_londres_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">Londres City</p>
<p class="font-italic">Quantité : <span class="qte">3</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
</ul>
<script type="text/javascript>
const qte = document.querySelectorAll('.qte');
const prix = document.querySelectorAll('.prix');
const prixPanier = document.querySelector('#prixPanier');
const TVA = document.querySelector('#TVA');
const Total = document.querySelector('#Total');
let prixTotal = 0;
for(let i=0; i < qte.length; i++){
prixTotal = prixTotal + (parseInt(qte[i].innerText)* parseFloat(prix[i].innerText));
}
prixPanier.innerText = prixTotal;
TVA.innerText = prixTotal * 0.15;
</script>
So what I'm looking for, is the right solution also for my last question, How can i add the total and the TVA so i can get the final or the total price ?
When you are working with numbers that contain symbols that are not detected or parsed with JavaScript internal functions, you should make sure to avoid those problems by simply removing the symbol before parsing anything.
This is how the code working looks like:
for(let i=0; i < qte.length; i++){
let price = parseFloat(prix[i].innerText.replace('€','').replace(',','.')),
quantity = parseInt(qte[i].innerText);
prixTotal += (quantity*price);
}
Also, it has kind of a better readability. I'll leave you a
Fiddle so you can check if it is giving your desired output:
https://jsfiddle.net/y0x84rwq/
You have some issues:
the price contain comma, need convert to dot before use.
let price = parseFloat(prix[i].innerHTML.replace(/,/g, '.')).toFixed(2);
This is worked code:
const qte = document.querySelectorAll('.qte');
const prix = document.querySelectorAll('.prix');
const prixPanier = document.querySelector('#prixPanier');
const TVA = document.querySelector('#TVA');
const Total = document.querySelector('#Total');
let prixTotal = 0.0;
for(let i=0; i < qte.length; i++){
let price = parseFloat(prix[i].innerText.replace(/,/g, '.')).toFixed(2);
//console.log(price)
prixTotal = prixTotal + (parseInt(qte[i].innerHTML)* price);
}
prixPanier.innerText = prixTotal;
TVA.innerText = prixTotal * 0.15;
<ul class="list-group list-group-flush">
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_newyork_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">New York City</p>
<p class="font-italic">Quantité : <span class="qte">1</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
<li class="list-group-item">
<div class="row">
<div class="col-md-4">
<img src="../img/produit_londres_0.jpeg" class="img-fluid float-left mr-5" width="80" height="60"/>
</div>
<div class="col-md-4">
<p class="mb-auto">Lego Architecture</p>
<p class="font-weight-bold">Londres City</p>
<p class="font-italic">Quantité : <span class="qte">3</span></p>
</div>
<div class="col-md-4">
<h4 class="text-right prix">49,99€</h4>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-outline-danger btn-sm float-right">Supprimer <i class="fas fa-trash-alt"></i></button>
</div>
</div>
</li>
</ul>
<div id="prixPanier"></div>
<div id="TVA"></div>

Categories