javascript - 从 API 数据切换 Div 隐藏/显示

标签 javascript python ajax rest flask

大家好我只想提前说声谢谢。我有几个问题想通过我的购物车页面解决。此应用程序是在 flask 中制作的。

cart

  1. 我有一个购物车,它使用来自用 python 创建的 Restful API 的数据动态填充表中的行。目前它还可以在 API 中添加价格并将其显示为小计的 html。我还可以点击项目旁边的删除按钮,它会从 API 中删除该特定元素。问题是 我需要能够在删除项目时更新小计 html。 是的,我可以点击删除按钮,刷新页面后它会显示正确的小计,但这是不现实的。

  2. 在购物车中添加和删除商品后,我在右上角的购物车图标上也有一个徽章,该徽章根据 API 中的元素数量递增。一旦我弄清楚(问题标记为 1)的问题,我就可以弄清楚如何在删除项目时减少徽章。我这里的主要问题是购物车在移动到网站的不同选项卡时没有显示徽章。 JS 链接到基本 html,但我猜因为 java 脚本没有在那些特定页面上运行不会显示。不确定如何解决这个问题。

  3. 如果购物车中没有商品,我想隐藏小计 html 和订购按钮。但出于某种原因,我无法让它切换,也不知道应该将代码放在哪里以检查 API 中是否没有项目。

我可能问得太多了,但如果可能的话,如果您有任何见解,请提供帮助。我将附上下面的 javascript 代码、我的 flask python 路由和购物车页面的 html。

定价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 %}

购物车 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 路由 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"})

我是菜鸟,所以这可能是一个冗长的问题,一个简单的问题。谢谢大家!

最佳答案

  1. 您可以尝试不将事件监听器绑定(bind)到每一行(就像您在循环中所做的那样),而是一次性绑定(bind)所有行。在 for 循环之后添加类似下面的代码并在循环中删除事件监听器,希望它能工作:

    document.querySelectorAll('.row-selector').on('click', function() {
        ... // do stuff with row 
    })
    
  2. 这个问题可以使用 flask 的 context_processor 来解决。您可以在 official documentation 中阅读更多相关信息.总之,您可以将徽章长度放在模板的上下文中,然后在模板的任何地方使用它,例如:

    @app.context_processor
    def inject_badge_length()
        badge_length = ... // calculate badge length for current user
        return {'BADGE_LENGTH': badge_length}
    

    然后您可以在模板中使用它,例如:

    <div class="badge-length">{{ BADGE_LENGTH }}</div>
    
  3. 最后,如果您有徽章长度(也可以为 0),您可以使用 css 和 javascript 隐藏小计 html,如下所示:

    #cart {
        opacity: 0;
    }
    
    #cart.active {
        opacity: 1;
    }
    

    并且在 js 中将其附加到 deleterow 事件函数(顺便说一下,在这种情况下可以是匿名(无名)函数):

    if (cartBadge.innerHTML === "0") {
        cart.classList.remove('active');
    }
    

    并在“addCartItem”函数末尾的某处追加:

    if (!cart.classList.contains('active') && cartBadge.innerHTML !== "0") {
        cart.classList.add('active');
    }
    

关于javascript - 从 API 数据切换 Div 隐藏/显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53876063/

相关文章:

javascript - 是否有理由嵌套 require 函数调用?

python - 比较数字时的奇怪行为

python - python中字符串float转int

javascript - 为什么success函数命令没有执行

Javascript 在基于 PrimeFaces 的页面中搞砸导航

javascript - 访问页面 AJAX 时自动 POST

javascript - 如何从异步调用返回响应?

javascript - scrillTop js 脚本无法正常工作

javascript - 将我的 amcharts flash 升级到 amcharts javascript

python - 如何使用 json 将编码音频字符串传递给字节?