0

I have some cards like this: enter image description here And I draw them with this function:

let createCard = (header, price, category, size, type, show, img) => {
    let card = document.createElement('div')
    card.className = 'card drk'
    document.querySelector('.container').appendChild(card)

    card.innerHTML = `
        <img src="${img}" alt="">
        <div class="card-description"> 
            <h3>${header}</h3>
            <ul>
                <li>Price: ${price}</li>
                <li>Category: ${category}</li>
                <li>Size: ${size}</li>
                <li>Type: ${type}</li>
                <li>Show: ${show}</li>
            </ul>
            <div class="button-holder">
                <button class="MoreBtn">More</button>
                <i class='bx bx-bookmark-alt'></i>
            </div>
        </div>
    `

    let menuBtn = document.querySelectorAll('.MoreBtn')
    menuBtn.forEach (item => item.addEventListener('click', () => {
        createMoreInfoCard(img, header, category, type, show, price)
    }))

    return card
}

And I want to trigger Last lines of above code <- this function on specific button click. As you can see I tried forEach but on click, it triggers all the buttons. So I want to get one specific button.

2 Answers2

0

try this way:

let createCard = (header, price, category, size, type, show, img) => {
  let card = document.createElement('div')
  card.className = 'card drk'
  document.querySelector('.container').appendChild(card)

  card.innerHTML = `
            <img src="${img}" alt="">
            <div class="card-description"> 
                <h3>${header}</h3>
                <ul>
                    <li>Price: ${price}</li>
                    <li>Category: ${category}</li>
                    <li>Size: ${size}</li>
                    <li>Type: ${type}</li>
                    <li>Show: ${show}</li>
                </ul>
                <div class="button-holder">
                    <button class="MoreBtn">More</button>
                    <i class='bx bx-bookmark-alt'></i>
                </div>
            </div>
        `
  card.addEventListener('click', (event) => {
    if (event.target.classList.contains('.MoreBtn'))
      createMoreInfoCard(img, header, category, type, show, price);
  });

  return card
}
Kosh
  • 16,966
  • 2
  • 19
  • 34
0

You don't have to keep track of how many buttons you have or will have in the future, and you just need one event handler bound to an ancestor element, you don't even need #ids.

In the example below there's only one clickhandler on a <section> -- any clicks within the section will invoke the event handler more(e). Because more(e) passes the event object (all event handlers do by default), e.target points to the element the user actually clicked. With that knowledge you can design the event handler to delegate the event by determining what reacts and what ignores the click event. In the example, only the elements with .more class can react and nothing else.

const sec = document.querySelector('section');
let data = [{
  img: `https://cdn.shopify.com/s/files/1/0268/7480/6357/products/cw7356-002_256x.jpg?v=1636057508`,
  name: 'Shoe',
  prc: '$90',
  cat: 'Apparal',
  desc: 'They go on your feet',
  mfg: 'Nike',
  pn: '256D8J'
}, {
  img: `https://cdn.shopify.com/s/files/1/0268/7480/6357/products/gm8646_1_400x.jpg?v=1614728158`,
  name: 'Hoodie',
  prc: '$50',
  cat: 'Apparal',
  desc: 'Keeps you warm',
  mfg: 'Adidas',
  pn: '881V9A'
}, {
  img: `https://cdn.shopify.com/s/files/1/0268/7480/6357/products/cw7356-002_256x.jpg?v=1636057508`,
  name: 'Shoe',
  prc: '$90',
  cat: 'Apparal',
  desc: 'They go on your feet',
  mfg: 'Nike',
  pn: '256D8J'
}, {
  img: `https://cdn.shopify.com/s/files/1/0268/7480/6357/products/gm8646_1_400x.jpg?v=1614728158`,
  name: 'Hoodie',
  prc: '$50',
  cat: 'Apparal',
  desc: 'Keeps you warm',
  mfg: 'Adidas',
  pn: '881V9A'
}];

const createDeck = (node, data) => {
  data.forEach((c, i) => {
    let card = `
<article class="card" data-idx='${i}'>
<img src="${c.img}">
<fieldset><legend><h3>${c.name} <br>${c.prc}</h3></legend><ul class='list'><li>Category: ${c.cat}</li>
<li>Size: ${c.desc}</li>        <li>Manufacturer: ${c.mfg}</li>      <li>Part No.: ${c.pn}</li>          </ul><button class="more">More</button></fieldset></article>`;
    node.insertAdjacentHTML('beforeEnd', card);
  });
};
const more = e => {
  const btn = e.target;
  if (btn.matches('.more')) {
    let list = btn.previousElementSibling;
    list.classList.toggle('open');
  }
};

createDeck(sec, data);

sec.onclick = more;
:root {
  font: 1ch/1.5 'Segoe UI'
}

body {
  font: 2ch
}

main {
  width: 100vw;
  height: 100vh;
  margin: 10px auto;
}

section {
  display: flex;
  flex-flow: row nowrap;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: max-content;
  padding: 5px 10px;
}

.card {
  display: flex;
  flex-flow: column nowrap;
  justify-content: center;
  align-items: center;
  width: 30vw;
  height: 100%;
  overflow-x: hidden
}

img {
  display: block;
  width: 30vw;
}

fieldset {}

legend {}

.list {
  display: none;
  font-size: 1rem;
  margin-left: -30px
}

.more {
  display: block;
  margin-left: 10vw;
  font: inherit;
}

.open {
  display: block
}
<main>
  <section></section>
</main>
zer00ne
  • 41,936
  • 6
  • 41
  • 68