Событие JavaScript onclick получает неверный идентификатор из динамически сгенерированного HTML-элемента - PullRequest
0 голосов
/ 05 ноября 2019

Используя mongodb и ejs в приложении NodeJS, я создал функцию, которая просматривает продукты в корзине и динамически показывает каждый из них на странице внутри таблицы.

Я пытаюсь создать функцию обновления количества, которая использует поле ввода для получения количества и кнопку для обновления базы данных.

Мой 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>
        <% }); %>

В целях тестирования javascript находится в теге <script> внизу страницы.

Мой код 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());
            }
        });
    }
});

Код выбирает следующий запрос GET из моей корзины. js:

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');
});

И модель моей корзины:

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;
    };
};

Логика работает нормально. Товар обновляется, цена и количество правильные. Общая цена и количество также являются правильными.

Однако, если у меня в корзине более одного товара (два разных товара), если я пытаюсь обновить количество второго товара (или любого товара, который не первый), при обновленииВместо этого обновляется количество первого товара.

Это вызвано тем, что обработчик событий, который обновляет количество, всегда получает идентификатор первого динамически генерируемого элемента на странице, а не тот, который я пытаюсь обновить. количество.

Это должно быть вызвано из-за циклического перебора продуктов в файле ejs, поэтому я подозреваю, что мне нужно выполнить какой-то цикл в функции js, чтобы получить правильный идентификатор, но я не уверен вэто.

1 Ответ

1 голос
/ 05 ноября 2019

Я нашел решение.

Я создал функцию, которая проверяет положение дочернего элемента (в данном случае tr) родителя (tbody с классом product-container в моем случае). ) которого был объявлен запрос на обновление.

Это цикл, который находит индекс:

for (let i = 0, len = block.children.length; i < len; i++) {

    (function(index) {
        block.children[i].onclick = function() {
            console.log(index);
        }
    })(i);
}

Вот как я реализовал его в своем коде:

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);
        }
    }
});
...