Skip to content
Advertisement

AddEventListener Not Working on Dynamic DOM

I have the following function which dynamically creates a Bootstrap card:

var createProductCard = function(productId, productName, cost, unit, description, src) {
    var card = document.createElement('DIV');
    card.classList.add('card');

    var img = document.createElement('IMG');
    img.classList.add('card-img-top');
    img.classList.add('w-100');
    img.classList.add('d-block');
    img.setAttribute('alt', productName + ' image unavaible');
    img.setAttribute('src', src);

    var cardBody = document.createElement('DIV');
    cardBody.classList.add('card-body');

    var cardTitle = document.createElement('H4');
    cardTitle.classList.add('card-title')
    cardTitle.innerText = productName;

    var cardSubtitle = document.createElement('H6');
    cardSubtitle.classList.add('card-subtitle')
    cardSubtitle.classList.add('mb-2')
    cardSubtitle.classList.add('text-muted')
    cardSubtitle.innerText = cost + ' - ' + unit;

    var cardText = document.createElement('P');
    cardText.classList.add('card-text');
    cardText.innerText = description;

    var button = document.createElement('BUTTON');
    button.classList.add('btn');
    button.classList.add('btn-primary');
    button.classList.add('add-card');
    button.setAttribute('data-id', productId);
    button.innerText = 'Add to Cart';
    button.addEventListener('click', addToCartClick, false);

    cardBody.appendChild(cardTitle);
    cardBody.appendChild(cardSubtitle);
    cardBody.appendChild(button);
    if (src) {
        card.appendChild(img);
    }
    card.appendChild(cardBody);

    return card;
}

Where I am declaring the button, I am attempting to use the addEventListener to generate the click event for the button. The addToCart function is defined as:

var addToCartClick = function() {
    var id = this.getAttribute('data-id');
    var card = products.find(function(product) {
        return product.ProductId === id;
    });

    cart.push(card);
}

And for what it is worth, this is how I am making my AJAX call to get the data:

window.onload = function() {
    var productsAll = document.getElementById('products-all');
    var xhttp = new XMLHttpRequest();
    xhttp.open('GET', '/server/api/product/query.php/', true);
    xhttp.setRequestHeader('Content-type', 'application/json');
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            var response = this.responseText; 
            var products = JSON.parse(response);
            if (!products.records) {
                return;
            }
            products = products.records;
            for (const key in products) {
                if (Object.hasOwnProperty.call(products, key)) {
                    const product = products[key];
                    var card = createProductCard(product.ProductId, product.ProductName, product.Cost, product.UnitName, product.Description, null);
                    productsAll.innerHTML += card.outerHTML;
                }
            }
        }
    };
    xhttp.send();
}

The issue is that the click event is never being invoked when I actually click on the button. I tried adding a debugger, setting up a breakpoint, and calling a console.log('click'); in the function, but the code never reaches any of those attempts when I click on the button.

I have also tried using onclick instead of click but with no success.

At this point, I’m not sure what I’m doing wrong.

Advertisement

Answer

I discovered the answer to my own question.

The solution was to use the appendChild method when adding my card to the parent. Documentation here: https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild

This was the change (in the last code block of my thread):

const product = products[key];
var card = createProductCard(product.ProductId, product.ProductName, product.Cost, product.UnitName, product.Description, null);
// productsAll.innerHTML += card.outerHTML;
productsAll.appendChild(card.outerHTML);
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement