Query selector returning undefine

Am trying to get the product name from my collection but am getting undefine as response
This is the js code

let stuff = document.querySelectorAll("#btn2")

 stuff.forEach((ele, index) => {
   let theObj = {}
   let name = ele.previousElementSibling.innerHtml
   let price = ele.parentNode.firstElementChild.lastElementChild.lastElementChild.innerHTML
 
    theObj['productName'] = name;
    theObj['price'] = price;
    

    ele.addEventListener("click", (e) => {
     
      let objectId = e.target.getAttribute("data-id")
      if(otherArr.indexOf(theObj) == -1){ 
           otherArr.push(theObj) ;
           addItem(theObj, objectId)
        
      } 
      event.preventDefault();
 })
 
  })

This is the Html code

<div id=products>
        <div id="items">
            <div id="imgTooltip">
              <img src="Images\product1.png" alt="">
              <div id="tooltip">
                <h2>Price</h2>
                <span>30000</span>
               </div>
        </div>
            <h3 id="proName">SAMSUNG TV</h3>
            <button id="btn2">ADD TO CART</button>
        </div>
        <div id="items">
            <div id="imgTooltip">
            <img src="Images\product2.png" alt="" >
            <div id="tooltip">
                <h2>Price</h2>
               <span>95000</span>
            </div>
        </div>
            <h3 id="proName">PIXEL 4a</h3>
            <button id="btn2">ADD TO CART</button>
        </div>
type or paste code here

When is this being called? If you aren’t waiting for the document to be ready, then it’s looking for btn2 before the DOM has been built.

Just as an aside. You can’t have the same id more than once. So querySelectorAll and an id don’t make sense. The JS will work as far as I know, but it’s invalid HTML.

You can add the defer attribute to the script tag, or wrap your code in a DOMContentLoaded handler, or just put the script element before the closing body tag. But if elements are dynamically added (like in a cart for example) you have to make sure you query for them at the right time and not just when the document loads.

Also,

ele.parentNode.firstElementChild.lastElementChild.lastElementChild.innerHTML

This is crackers, it’s incredibly confusing and it’s near guaranteed you will make a tiny change to some HTML and break it.

As pointed out, you’ve got duplicate IDs. It should ideally be something like class="item" id="item-123".

At the very least, query “products”, and forEach through each child of that

thanks for the reply, i actually query for the btn2 when the button get clicked not when the page load

It doesn’t matter when you do it. Using querySelectorAll with an id selector doesn’t make sense as there should only be one of each id in the HTML.

Just to be clear I’m talking about this line:

let stuff = document.querySelectorAll("#btn2")

have changed it, but am still having the same issue

let stuff = document.querySelectorAll(".btn2")

What exactly is undefined, the stuff variable or what the click handler returns?

You’re trying to access data-id here:

let objectId = e.target.getAttribute("data-id")

But e.target is the button, it has no custom data attribute.

Thanks, have solved it. Am trying to access the node list around the btn2 class

I would suggest not using the DOM as data storage.

It’s fine to display data, but using the DOM as live storage (adding/updating/retrieving) of data directly, isn’t really a good idea. It is in my opinion a potential bad mental model to get into. Because that is not how it would normally work. You would be getting the products and their data from some back-end and in my opinion, it’s better to get in the habit of thinking of DOM content, like products, as external data. The same goes for other such learning projects, like say a todo list.

You do not need a real back-end or database for this. You can just create an array of objects or use a JSON file for the data. Then have the DOM reflect that data. This means you update the data and the DOM will just render it. Making the DOM content just a view representation of data.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.