javascript - Wrong ID is being returned when clicking button - Stack Overflow

admin2025-04-15  0

product cardsI need a help of solving my below issues:

I have generated dynamically cards with javascript and try to get the id when product is clicked.The results what i Have done are:

1)when click the first product it gets the wrong id,showing the details of the last product 2)the event listener works only for the first element so i can't show the other product.

product-list.js

    let cardData = [
    {
        id: 1,
        imgFile: 'images/products/marievi5.jpg',
        heading: 'Marievi the Influencer',
        body: 'this is card body',
        price: 150,


    },
    {
        id: 2,
        imgFile: 'images/products/rock1.jpg',
        heading: 'card 2',
        body: 'this is card body',
        price: 200,

    },
    {
        id: 3,
        imgFile: 'images/products/marievi5.jpg',
        heading: 'card 3',
        body: 'this is card body',
        price: 400,

    },
    {
        id: 4,
        imgFile: 'images/products/marievi5.jpg',
        heading: 'card 4',
        body: 'this is card body',
        price: 300,

    },
];


const createCard = () => {
    
    let cardContainer = document.querySelector('.card-container');
    cardContainer.innerHTML = ''; // Clear the grid first

    cardData.forEach((data) => {
        //create product card
        let card = document.createElement('div');
        card.classList.add('card-body');
        card.setAttribute('data-product-id', data.id);

        // Add content inside the product card
        let content = `<div class="card-container  py-5">
        
             <div class="row  ">
                <div class="col">
                <div class="listProduct">
        
                    <div class="card-body product-card" data-product-id="${data.id}">
                        <img class="card-img-top " id="productImg" src="${data.imgFile}" alt="Card image cap">

                            <div class=" product-details" id="details-${data.id}">
                                <h5 class="card-title mb-3 fw-bold ">${data.heading}</h5>
                                <p class="card-text text-muted mb-4">${data.body}</p>
                                <div class="d-flex justify-content-between align-items-center">
                                <span class="product-price">Price:${data.price}</span>
                            </div>
                            <button class="btn btn-custom text-white px-4 py-2 rounded-pill" data-product-id="${data.id}"btn btn-primary">View Details</button>
                    </div>
                    </div>
                </div>
                
                </div>
                </div>
                 
        </div>`;

        cardContainer.innerHTML += content;
       


            document.querySelector('.listProduct').addEventListener('click',function(){

                let productId = data.id;  // This should not be undefined
                console.log(productId);
                window.location.href = `ProductDetails1.html?id=${productId}`;

            });

       
        return card;

    })

}

// Call the function to generate products on page load
createCard(cardData);

ProductDetails.html

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Product Details</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=1.0">
    <meta charset="utf-8">

    <link href="/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

    <script src="/[email protected]/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>

    <script src=".js" crossorigin="anonymous"></script>
    <script src="//code.jquery/jquery.min.js"></script>

    <link rel="stylesheet" href="mystyle.css">
    <link rel="stylesheet" href="ProductDetails.css">

</head>


<body>

    <!--Navigation bar-->
    <div id="nav-placeholder">

    </div>

    <script>
        $(function () {
            $("#nav-placeholder").load("nav.html");
        });
    </script>

   

    <div class="container my-5 pt-5">


        <div class=" row mt-5">
            <div class="col-sm-8 d-flex flex-column d-inline-flex p-2 bd-highlight justify-content-around ">
                <div class="detail">
                    <figure class="ProductItem-gallery">

                        <div class="image1">
                            <img src="" alt="">
                            
                        </div>
                        
                    </figure>

                    <div class="col">
                        <div class="content">
                            <h1 class="name"></h1>
                            <p class="price"></p>
                            <p class="description"></p>
                            <button class="btn btn-primary">Add to Cart</button>

                        </div>

                    </div>
                </div>
            </div>
        </div>
    </div>


    <script>

        let products = null;
        fetch('./products.json')
            .then(response => response.json())
            .then(data => {
                products = data;
                showDetail();
            })
        //find this product
        function showDetail() {
            let detail = document.querySelector('.detail');
            let productId = new URLSearchParams(window.location.search).get('id');

            console.log("product id  "+productId);

            let thisProduct = products.filter(value => {
                return value.id == productId
            })[0];

            //if there is no product has id =productId
            //=>return to home page
            if (!thisProduct) {
                window.location.href = "/shoplist.html";
            }

            //and if has,add data this product in html
            detail.querySelector('.image1 img').src = thisProduct.imgFile;
            detail.querySelector('.name').innerText = thisProduct.heading;
            detail.querySelector('.price').innerText = '$' + thisProduct.price;
            detail.querySelector('.description').innerText = thisProduct.body;

        }
    </script>
</body>

</html>

shoplist.html

<!DOCTYPE html>
<html lang="en">

<head>
    <title>ShopList</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=1.0">
    <meta charset="utf-8">

    <link href="/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

    <script src="/[email protected]/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>

    <script src=".js" crossorigin="anonymous"></script>
    <!-- <script src=".10.2.js"></script> -->



    <link rel="stylesheet" href="shopstyle.css">
    <link rel="stylesheet" href="mystyle.css">
    <script src="//code.jquery/jquery.min.js"></script>
</head>


<body>

    <!--Navigation bar-->
    <div id="nav-placeholder">

    </div>

    <script>
        $(function () {
            $("#nav-placeholder").load("nav.html");
        });
    </script>


    <h1 class="heading-top-op text-center">Original Paintings</h1>


    <div class="card-container">
        <div class="listProduct"></div>

        

    </div>


    <script src="product-list.js" defer>
    </script>

    <script>

        let products = null;
        fetch('./products.json')
            .then(response => response.json())
            .then(data => {
                products = data;
                console.log(products);
                addDataToHTML();
            })

        let listProduct = document.querySelector('.listProduct');
        function addDataToHTML() {
            products.forEach(product => {
                //create new element item
                let newProduct = document.createElement('a');
                newProduct.setAttribute("id", "clicktag");
                newProduct.href = '/ProductDetails1.html?id=' + product.id;


                

                newProduct.classList.add('item');
                newProduct.innerHTML = `
                    <img src="${product.imgFile}"/>;
                    <h2>${product.heading}</h2>;
                    <p class="price">${product.price}</p>`;


                //add this element in listProduct class
                listProduct.appendChild(newProduct);

            })
            // end - of for 
        }
        // end of fuction addDataToHtML
      




    </script>

</body>

<!--footer -->
<div id="footer-placeholder">

</div>

<script>
    $(function () {
        $("#footer-placeholder").load("footer.html");
    });
</script>

</html>

product cardsI need a help of solving my below issues:

I have generated dynamically cards with javascript and try to get the id when product is clicked.The results what i Have done are:

1)when click the first product it gets the wrong id,showing the details of the last product 2)the event listener works only for the first element so i can't show the other product.

product-list.js

    let cardData = [
    {
        id: 1,
        imgFile: 'images/products/marievi5.jpg',
        heading: 'Marievi the Influencer',
        body: 'this is card body',
        price: 150,


    },
    {
        id: 2,
        imgFile: 'images/products/rock1.jpg',
        heading: 'card 2',
        body: 'this is card body',
        price: 200,

    },
    {
        id: 3,
        imgFile: 'images/products/marievi5.jpg',
        heading: 'card 3',
        body: 'this is card body',
        price: 400,

    },
    {
        id: 4,
        imgFile: 'images/products/marievi5.jpg',
        heading: 'card 4',
        body: 'this is card body',
        price: 300,

    },
];


const createCard = () => {
    
    let cardContainer = document.querySelector('.card-container');
    cardContainer.innerHTML = ''; // Clear the grid first

    cardData.forEach((data) => {
        //create product card
        let card = document.createElement('div');
        card.classList.add('card-body');
        card.setAttribute('data-product-id', data.id);

        // Add content inside the product card
        let content = `<div class="card-container  py-5">
        
             <div class="row  ">
                <div class="col">
                <div class="listProduct">
        
                    <div class="card-body product-card" data-product-id="${data.id}">
                        <img class="card-img-top " id="productImg" src="${data.imgFile}" alt="Card image cap">

                            <div class=" product-details" id="details-${data.id}">
                                <h5 class="card-title mb-3 fw-bold ">${data.heading}</h5>
                                <p class="card-text text-muted mb-4">${data.body}</p>
                                <div class="d-flex justify-content-between align-items-center">
                                <span class="product-price">Price:${data.price}</span>
                            </div>
                            <button class="btn btn-custom text-white px-4 py-2 rounded-pill" data-product-id="${data.id}"btn btn-primary">View Details</button>
                    </div>
                    </div>
                </div>
                
                </div>
                </div>
                 
        </div>`;

        cardContainer.innerHTML += content;
       


            document.querySelector('.listProduct').addEventListener('click',function(){

                let productId = data.id;  // This should not be undefined
                console.log(productId);
                window.location.href = `ProductDetails1.html?id=${productId}`;

            });

       
        return card;

    })

}

// Call the function to generate products on page load
createCard(cardData);

ProductDetails.html

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Product Details</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=1.0">
    <meta charset="utf-8">

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>

    <script src="https://kit.fontawesome.com/ce111f8d46.js" crossorigin="anonymous"></script>
    <script src="//code.jquery.com/jquery.min.js"></script>

    <link rel="stylesheet" href="mystyle.css">
    <link rel="stylesheet" href="ProductDetails.css">

</head>


<body>

    <!--Navigation bar-->
    <div id="nav-placeholder">

    </div>

    <script>
        $(function () {
            $("#nav-placeholder").load("nav.html");
        });
    </script>

   

    <div class="container my-5 pt-5">


        <div class=" row mt-5">
            <div class="col-sm-8 d-flex flex-column d-inline-flex p-2 bd-highlight justify-content-around ">
                <div class="detail">
                    <figure class="ProductItem-gallery">

                        <div class="image1">
                            <img src="" alt="">
                            
                        </div>
                        
                    </figure>

                    <div class="col">
                        <div class="content">
                            <h1 class="name"></h1>
                            <p class="price"></p>
                            <p class="description"></p>
                            <button class="btn btn-primary">Add to Cart</button>

                        </div>

                    </div>
                </div>
            </div>
        </div>
    </div>


    <script>

        let products = null;
        fetch('./products.json')
            .then(response => response.json())
            .then(data => {
                products = data;
                showDetail();
            })
        //find this product
        function showDetail() {
            let detail = document.querySelector('.detail');
            let productId = new URLSearchParams(window.location.search).get('id');

            console.log("product id  "+productId);

            let thisProduct = products.filter(value => {
                return value.id == productId
            })[0];

            //if there is no product has id =productId
            //=>return to home page
            if (!thisProduct) {
                window.location.href = "/shoplist.html";
            }

            //and if has,add data this product in html
            detail.querySelector('.image1 img').src = thisProduct.imgFile;
            detail.querySelector('.name').innerText = thisProduct.heading;
            detail.querySelector('.price').innerText = '$' + thisProduct.price;
            detail.querySelector('.description').innerText = thisProduct.body;

        }
    </script>
</body>

</html>

shoplist.html

<!DOCTYPE html>
<html lang="en">

<head>
    <title>ShopList</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=1.0">
    <meta charset="utf-8">

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
        crossorigin="anonymous"></script>

    <script src="https://kit.fontawesome.com/ce111f8d46.js" crossorigin="anonymous"></script>
    <!-- <script src="https://code.jquery.com/jquery-1.10.2.js"></script> -->



    <link rel="stylesheet" href="shopstyle.css">
    <link rel="stylesheet" href="mystyle.css">
    <script src="//code.jquery.com/jquery.min.js"></script>
</head>


<body>

    <!--Navigation bar-->
    <div id="nav-placeholder">

    </div>

    <script>
        $(function () {
            $("#nav-placeholder").load("nav.html");
        });
    </script>


    <h1 class="heading-top-op text-center">Original Paintings</h1>


    <div class="card-container">
        <div class="listProduct"></div>

        

    </div>


    <script src="product-list.js" defer>
    </script>

    <script>

        let products = null;
        fetch('./products.json')
            .then(response => response.json())
            .then(data => {
                products = data;
                console.log(products);
                addDataToHTML();
            })

        let listProduct = document.querySelector('.listProduct');
        function addDataToHTML() {
            products.forEach(product => {
                //create new element item
                let newProduct = document.createElement('a');
                newProduct.setAttribute("id", "clicktag");
                newProduct.href = '/ProductDetails1.html?id=' + product.id;


                

                newProduct.classList.add('item');
                newProduct.innerHTML = `
                    <img src="${product.imgFile}"/>;
                    <h2>${product.heading}</h2>;
                    <p class="price">${product.price}</p>`;


                //add this element in listProduct class
                listProduct.appendChild(newProduct);

            })
            // end - of for 
        }
        // end of fuction addDataToHtML
      




    </script>

</body>

<!--footer -->
<div id="footer-placeholder">

</div>

<script>
    $(function () {
        $("#footer-placeholder").load("footer.html");
    });
</script>

</html>
Share Improve this question edited Feb 5 at 7:11 DarkBee 15.5k8 gold badges72 silver badges118 bronze badges asked Feb 4 at 12:27 EvitaEvita 34 bronze badges 4
  • 3 document.querySelector('.listProduct') will always return the first matching element it finds within the document. – C3roe Commented Feb 4 at 12:38
  • let productId = data.id; // This should not be undefined - data does not exist within the scope of your click handler callback function. – C3roe Commented Feb 4 at 12:40
  • Please click edit, then [<>] and provide a minimal reproducible example using RELEVANT RENDERED HTML and RELEVANT JS – mplungjan Commented Feb 4 at 13:09
  • Please see How to Ask and take the tour. Your title should be a clear, specific question. – isherwood Commented Feb 4 at 14:24
Add a comment  | 

1 Answer 1

Reset to default 1

I recreated the requirement which is you asked, Hope this will work for you

Incorrect event binding :

  • You are using document.querySelector('.listProduct'), which only selects the first .listProduct element. This is why only one product is clickable.
  • Wrong productId assignment – Inside the click event, you're using data.id, which always refers to the last iteration value. This is why the wrong product ID is being used.

So i recreated the flow:

  • I attached event listeners after inserting the cards into the DOM.
  • I used querySelectorAll to select all buttons and add event listeners properly.
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Product Cards</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>

<body>
    <div class="container">
        <div class="row card-parent"></div>
    </div>

    <script>
        let cardData = [
            { id: 1, imgFile: 'images/products/marievi5.jpg', heading: 'Marievi the Influencer', body: 'This is card body', price: 150 },
            { id: 2, imgFile: 'images/products/rock1.jpg', heading: 'Card 2', body: 'This is card body', price: 200 },
            { id: 3, imgFile: 'images/products/marievi5.jpg', heading: 'Card 3', body: 'This is card body', price: 400 },
            { id: 4, imgFile: 'images/products/marievi5.jpg', heading: 'Card 4', body: 'This is card body', price: 300 }
        ];

        const createCard = () => {
            let cardContainer = document.querySelector('.card-parent');
            cardContainer.innerHTML = '';  

            cardData.forEach((data) => {
                let card = document.createElement('div');
                card.classList.add('col-md-4', 'mb-4');

                card.innerHTML = `
                    <div class="card shadow-sm">
                        <img class="card-img-top" src="${data.imgFile}" alt="Product Image">
                        <div class="card-body">
                            <h5 class="card-title fw-bold">${data.heading}</h5>
                            <p class="card-text text-muted">${data.body}</p>
                            <div class="d-flex justify-content-between align-items-center">
                                <span class="product-price fw-bold">$${data.price}</span>
                                <button class="btn btn-primary view-details-btn" data-product-id="${data.id}">View Details</button>
                            </div>
                        </div>
                    </div>
                `;

                cardContainer.appendChild(card); // use appendChild here instead of innerHtml, because innerHtml will remove the existing cards
            });


            document.querySelectorAll('.view-details-btn').forEach((button) => { // Here i used View Details button class instead of card class
                button.addEventListener('click', function () {
                    let productId = this.getAttribute('data-product-id'); // taking the all card buttons and add event listener to listen click event and then take id using getAttribute
                    window.location.href = `ProductDetails1.html?id=${productId}`;
                });
            });
        }

        createCard();
    </script>
</body>

</html>

转载请注明原文地址:http://www.anycun.com/QandA/1744720156a86683.html