Issue
Hello all I just want to say thank you in advance. I have a few issues that I would like to address with my shopping cart page. This application is made in flask.
I have a cart that dynamically populates rows in a table with data from a Restful API created with python. At the moment it can also add the prices within the API and display it as the subtotal's html. I can also hit the delete button next to the item and it deletes that particular element out of the API. The issue is I need to be able to update the subtotal html upon deleting the item. Yes I can hit the delete button and upon refreshing the page it will show the correct subtotal but this is unrealistic.
Upon adding and deleting items in cart I also have a badge on the shopping cart icon in the upper right hand corner that increments according to how many elements are in API. Once I figure out issue with (problem labeled 1) I can figure out how to make the badge decrease upon item deletion. My main issue here is the cart shows no badge upon moving to different tabs of the website. The JS is linked to the base html, but I guess since the java script is not running on those particular pages it's not going to show. Not to sure how to work around this.
If there are no items in cart I would like to hide the subtotal html and order button. But for some reason I can't get it to toggle and don't know where I should put the code to check if there are no items in API.
I'm probably asking too much but if possible please help if you may have any insight. I'll be attaching the code below for javascript, my flask python route, and the html for the cart page.
Pricing pricing.html
p{% extends 'base.html' %}
{% block content %}
<h1>Pricing</h1>
<div class="row">
<div class="container col-sm-6">
<div class="container border">
<table id='table'>
<thead>
<th><h5>Equipment</h5></th>
<th "><h5>Price</h5></th>
</thead>
{% for quip in pricing %}
<tr style="height:25px;" class="border">
<td id='pricewidth'>{{quip}}</td>
<td id='pricewidth' style='text-align:center;'>{{pricing[quip]}}</td>
<td ><button type="button" name="button" class="btn btn-primary">Add</button></td>
</tr>
{% endfor %}
</table>
</div>
</div>
<div class="container col-sm-6">
<table id='cart'>
</table>
<div id='pricefooter'>
<h1 style='margin-top:25px; border-top:.5px black solid;'>Subtotal: $<span id='subtotal'>0</span></h1>
<form action="{{url_for('Order')}}"><button type="submit" name="button" class='btn btn-warning'>Order</button></form>
</div>
</div>
</div>
{% endblock content %}
Cart Javascript pricecart.js
var tablerows = document.getElementById('table').rows.length;
var table = document.getElementById('table');
var cart = document.getElementById('cart');
var subtotal = document.getElementById('subtotal');
var username = document.getElementById('username').innerHTML;
var cartBadge = document.getElementById('cartbadge');
var pricesub = document.getElementById('pricefooter');
// On load cart
window.onload = function wowzers(){
var array = [];
var sum = 0;
// Get Data
var xhr = new XMLHttpRequest();
xhr.open('GET', 'pricing/orders/' + username +'/api', true);
xhr.onload = function(){
var data = JSON.parse(this.response);
cartBadge.innerHTML = data.length
if(xhr.status >= 200 && xhr.status < 400){
for(x in data){
for(key in data[x]){
array.push(Number(data[x][key]));
sum+=Number(data[x][key]);
subtotal.innerHTML = sum;
row = cart.insertRow(-1);
// Delete Data
row.addEventListener('click', function deleterow(){
index = this.rowIndex;
// subtotal.innerHTML = sum-Number(cart.rows[index].cells[1].innerHTML);
$.post('pricing/orders/delete', {
delete_item: index
});
cart.deleteRow(index);
});
cell1 = row.insertCell(0);
cell2 = row.insertCell(1);
cell3 = row.insertCell(2);
cell1.innerHTML = key;
cell2. innerHTML = data[x][key];
cell3. innerHTML = "<button class='btn btn-danger'>Delete</button>"
}
}
console.log(sum);
}else{
console.log(error)
}
}
xhr.send()
}
//Dynamic Cart
for(x = 0; x < tablerows; x++){
table.rows[x].addEventListener('click', addCartItem);
}
function addCartItem(ev){
var array = [];
var sum = 0;
index = this.rowIndex;
equipmentCell = table.rows[index].cells[0];
priceCell = table.rows[index].cells[1];
equipmentName = equipmentCell.innerHTML;
equipmentPrice = priceCell.innerHTML;
// Post Data
$.post('/pricing/orders/' + username + '/api', {
javascript_data: JSON.stringify({[equipmentName]:equipmentPrice})
});
cartrow = cart.insertRow(-1);
// Delete Data
cartrow.addEventListener('click', function deleterow(){
index = this.rowIndex;
// subtotal.innerHTML = sum-Number(cart.rows[index].cells[1].innerHTML);
$.post('pricing/orders/delete', {
delete_item: index
});
cart.deleteRow(index);
});
cell1 = cartrow.insertCell(0);
cell2 = cartrow.insertCell(1);
cell3 = cartrow.insertCell(2);
cell1.innerHTML= equipmentName;
cell2.innerHTML = equipmentPrice;
cell3.innerHTML = "<button class='btn btn-danger'>Delete</button>";
// Open Api information
var xhr = new XMLHttpRequest();
xhr.open('GET', 'pricing/orders/' + username +'/api', true);
xhr.onload = function(){
var data = JSON.parse(this.response);
cartBadge.innerHTML = data.length
if(xhr.status >= 200 && xhr.status < 400){
for(x in data){
for(y in data[x]){
array.push(Number(data[x][y]));
sum+=Number(data[x][y]);
subtotal.innerHTML = sum;
}
}
}else{
console.log(error);
}
}
xhr.send();
}
Flask Route routes.py
@app.route('/pricing/orders/<user_name>/api', methods=['POST', 'GET'])
@login_required
def api(user_name):
user_name = current_user.username
if request.method == 'POST':
cart.append(json.loads(request.form["javascript_data"]))
return jsonify(cart)
@app.route('/pricing/orders/delete', methods=['POST', 'GET'])
@login_required
def delete_item():
if request.method == 'POST':
print(cart[json.loads(request.form["delete_item"])])
cart.pop(json.loads(request.form["delete_item"]))
print(cart)
return jsonify({"whoa": "there"})
I'm a noob so this may be quite the long winded question an easy problem. Thanks guys!
Solution
You can try to bind event listener not to every single row (like you do in the loop), but for all of them in one time. After for loop add something like code below and remove event-listener in the loop, hope it will work:
document.querySelectorAll('.row-selector').on('click', function() { ... // do stuff with row })
This problem can be solved using flask's context_processor. You can read more about it in official documentation. In a word you can put badge length in template's context and then use it anywhere in your templates, for example:
@app.context_processor def inject_badge_length() badge_length = ... // calculate badge length for current user return {'BADGE_LENGTH': badge_length}
and then you can use it in template like:
<div class="badge-length">{{ BADGE_LENGTH }}</div>
Finally, if you have badge length (which can also be 0) you can hide subtotal html using css and javascript, like this:
#cart { opacity: 0; } #cart.active { opacity: 1; }
and in js append this to the deleterow event-function (which, by the way, can be anonymous (nameless) function in this case):
if (cartBadge.innerHTML === "0") {
cart.classList.remove('active');
}
and somewhere in the end of 'addCartItem' function append:
if (!cart.classList.contains('active') && cartBadge.innerHTML !== "0") {
cart.classList.add('active');
}
Answered By - Anlis
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.