[英]JavaScript onclick event gets the wrong id from dynamically generated html element
Using mongodb and ejs in a NodeJS application, I have created a function that loops through products in the shopping cart and dynamically shows each one of them on the page, inside a table.在 NodeJS 应用程序中使用 mongodb 和 ejs,我创建了一个 function 循环浏览购物车中的产品,并在页面上的表格内动态显示它们中的每一个。
I am trying to create a quantity update function that uses an input field to take the quantity and a button to update the database.我正在尝试创建一个数量更新 function,它使用一个输入字段来获取数量和一个按钮来更新数据库。
My HTML:我的 HTML:
<tbody class="product-container">
<!-- loop through each product -->
<% products.forEach (function(element) { %>
<tr valign="top" class="cart-p-list">
<!-- get individual unique ID for each product -->
<input type="hidden" class="id" value="<%= element.item._id %>">
<td class="col-qty cart-p-qty nowrap" align="right">
<div class="proopc-input-append">
<!-- input for quantity and update button -->
<input type="number" class="input-ultra-mini proopc-qty-input qty" size="1" maxlength="4" name="quantity" value="<%= element.qty %>" data-quantity="<%= element.qty %>" step="1" min="1" max="50">
<button class="proopc-btn proopc-task-updateqty updateproduct" name="updatecart.0" title="Update Quantity In Cart"><i class="proopc-icon-refresh"></i></button>
</div>
</td>
</tr>
<% }); %>
For test purposes, the javascript is in a <script>
tag at the bottom of the page.出于测试目的,javascript 位于页面底部的
<script>
标记中。
My JavaScript code:我的 JavaScript 代码:
window.addEventListener('load', function() {
{
// Update Quantity of product in shopping cart
const block = document.querySelector('.product-container');
block.addEventListener('click', function(e) {
if (e.target.classList.contains('updateproduct')) {
console.log(e);
let id = e.target.parentNode.parentNode.parentNode.parentNode.querySelector('.id').value;
let qty = +e.target.parentNode.querySelector('.qty').value;
console.log(id);
fetch(`/update/${id}/${qty}`, {
method: 'GET'
}).then((res) => res.text());
}
});
}
});
The code fetches the following GET request from my cart.js:该代码从我的 cart.js 中获取以下 GET 请求:
router.get('/update/:id/:qty', function (req, res, next) {
let productId = req.params.id;
let quantity = +req.params.qty;
let cart = new Cart(req.session.cart ? req.session.cart : {});
cart.update(productId, quantity);
req.session.cart = cart;
res.redirect('back');
});
And my cart model:还有我的购物车 model:
module.exports = function Cart(oldCart) {
this.items = oldCart.items || {};
this.totalQty = oldCart.totalQty || 0;
this.totalPrice = oldCart.totalPrice || 0;
this.update = function (id, quantity) {
let currentQuantity = this.items[id].qty;
let newQuantity = this.items[id].qty = quantity;
let currentPrice = this.items[id].price;
let newPrice = this.items[id].item.price * quantity;;
this.items[id].price = this.items[id].item.price * quantity;
this.totalQty -= currentQuantity;
this.totalQty += newQuantity;
this.totalPrice -= currentPrice;
this.totalPrice += newPrice;
};
this.generateArray = function () {
let arr = [];
for (let id in this.items) {
arr.push(this.items[id]);
}
return arr;
};
};
The logic is working fine.逻辑工作正常。 The product is being updated, the price and quantity are correct.
产品正在更新中,价格和数量是正确的。 The total price and quantity are also correct.
总价和数量也是正确的。
However, if I have more than one product in the cart (two different products), if I try to update the quantity of the second product (or any product that's not the first one), on refresh, the quantity of the first product is updated instead.但是,如果我在购物车中有多个产品(两种不同的产品),如果我尝试更新第二个产品(或任何不是第一个产品)的数量,刷新时,第一个产品的数量是而是更新了。
This is caused because the eventlistener that updates the quantity, always takes the id of the first dynamically generated item on the page instead of the one that I am trying to update the quantity of.这是因为更新数量的事件监听器总是采用页面上第一个动态生成的项目的 id,而不是我试图更新数量的那个。
This must be caused because of looping through the products in the ejs file, so I suspect I need to do some sort of looping in the js function to get the correct id, but I am unsure of this.这一定是由于循环遍历 ejs 文件中的产品造成的,所以我怀疑我需要在 js function 中进行某种循环以获得正确的 id,但我不确定这一点。
I figured out a solution.我想出了一个解决办法。
I created a function that checks the position of the child ( tr
in this case) of a parent ( tbody
with the class product-container
in my case) of which the update request was declared.我创建了一个 function 来检查父母的孩子(在这种情况下为
tr
)的 position(在我的情况下声明了更新请求的tbody
与 class product-container
)。
This is the loop that finds the index:这是找到索引的循环:
for (let i = 0, len = block.children.length; i < len; i++) {
(function(index) {
block.children[i].onclick = function() {
console.log(index);
}
})(i);
}
This is how I implemented it in my code:这就是我在代码中实现它的方式:
document.addEventListener('DOMContentLoaded', function() {
{
// Update Quantity of product in shopping cart
const block = document.querySelector('.product-container');
// Fetch an array of all ids
let ids = document.querySelectorAll('.id');
// Create a function that shows the index of the child of the parent block
for (let i = 0, len = block.children.length; i < len; i++) {
(function(index) {
block.children[i].onclick = function(e) {
if (e.target && e.target.classList.contains('updateproduct')) {
// ID now equals the id of the clicked child of the container
let id = ids[index].value;
let qty = +e.target.parentNode.querySelector('.qty').value;
fetch(`/update/${id}/${qty}`, {
method: 'GET'
}).then((res) => res.text()).then(() => window.history.go());
}
}
})(i);
}
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.