I am trying to understand why this onclick button is only working once.
Basically I am testing to see if the "heart" or "wishlist" button is clicked on. When clicked, console.log the name of the product so I can confirm it. But it only picks up the first product. When I click the wishlist button on the second product.
It gives this error "Uncaught SyntaxError: Invalid or unexpected token (at products:1:10)"
When I go to that line it just show ''
I have also tried using a
const wishlistBtn = document.querySelector('.wishlistBtn');
wishlistBtn.addEventListener('click', (product_name) => { console.log(product_name) })
But it just returns that the property is null. I'm wondering if the reason is because of the innerHTML I am including all of this in.
Javascript:
const getProducts = () => {
return fetch('/get-products', {
method: 'POST',
headers: new Headers({'Content-Type':'application/json'}),
body: JSON.stringify({})
})
.then(res => res.json())
.then(data => {
createProductCards(data);
})
}
var wishlist = (product_name) => {
console.log(product_name);
}
const createProductCards = (data) => {
let parent = document.querySelector('.container');
let start = '<div >';
let middle = '';
let end = '</div>';
for(let i = 0; i < data.length; i ){
if(data[i].id != decodeURI(location.pathname.split('/').pop()) && !data[i].draft){
middle = `
<div >
<div >
${data[i].discount === '0' ? ``:`
<span >${data[i].discount}% off</span>
`}
<img src="${data[i].images[0]}" alt="">
<button onclick="wishlist('${data[i].name}')"><i ></i></button>
</div>
<div >
<h6 ><a href="/products/${data[i].id}">${data[i].name}</a></h6>
${data[i].discount === '0' ? `<span >$${data[i].totalPrice}</span>`:`
<span >$${data[i].totalPrice}</span>
<span >$${data[i].actualPrice}</span>
`}
</div>
</div>
`;
}
}
parent.innerHTML = start middle end;
}
getProducts();
CodePudding user response:
document.querySelector
only returns the first instance of the selector. So the first wish list button on your page is the only one that gets a listener attached.
If you're coming from JQuery, this is a nuanced difference. To add the event listener to every .wishlistBtn
you could do something like:
const wishlistBtns = document.querySelectorAll('.wishlistBtn');
[...wishlistBtns].forEach(wishListButton => wishListButton.addEventListener('click', (product_name) => { console.log(product_name) })
There are two differences:
- The use of
querySelectorAll
returns a NodeList of all of the elements that match the.wishlistBtn
selector. - Iterate over the NodeList and add an event listener to each individual node. Unfortunately NodeList isn't exactly an array so
[...wishlistButtons]
is a quick and dirty way to convert it to an array using the relatively new spread operator...
CodePudding user response:
document.querySelector
works only on the first matched element. You may need to use document.querySelectorAll
& attach event after the for loop has completely finished it's execution
const wishlistBtn = document.querySelectorAll('.wishlistBtn').forEach((item) => {
item.addEventListener('click', getProductName)
})
function getProductName(product_name) {
console.log(product_name)
})
Here is an example
document.querySelectorAll('.test').forEach(item => {
item.addEventListener('click', getButtonValue)
})
function getButtonValue(elem) {
console.log(elem.target.innerHTML)
}
<button >1</button>
<button >2</button>
<button >3</button>
<button >4</button>
<button >5</button>
<button >6</button>