skip to Main Content

I have 2 buttons and when the buttons are clicked it should bring up products based on the appropriate category. However, there is such a problem that when you click the button for the second time, these products come again, repeating continuously. I want it to click once and arrive once, not every time. How can I prevent this?

const arr = [

    {
        "id": "1",
        "Name": "Coke 500ml",
        "Price": "80",
        "Quantity": "50",
        "Category": "bike"
    },

    {
        "id": "2",
        "Name": "Cake",
        "Price": "150",
        "Quantity": "40",
        "Category": "clothing"
    },

    {
        "id": "3",
        "Name": "Beef Ribs",
        "Price": "100",
        "Quantity": "50",
        "Category": "clothing"
    },

    {
        "id": "4",
        "Name": "Cabbage Salad",
        "Price": "50",
        "Quantity": "30",
        "Category": "clothing"
    },

    {
        "id": "5",
        "Name": "Cake",
        "Price": "150",
        "Quantity": "30",
        "Category": "bike"
    },

    {
        "id": "6",
        "Name": "Beef Ribs",
        "Price": "100",
        "Quantity": "30",
        "Category": "bike"
    }
];

const row = document.querySelector('.row')

function filterArrayByCategory(category) {
    const a = arr.filter(el => el.Category === category);
    console.log(a);

    a.map(element => {
        const div = document.createElement('div')
        div.className = 'col-lg-4 col-md-4 col-sm-6 col-12 p-3'
        div.innerHTML = `
                    <div class="card" style="width: 18rem; height: 100% ">
                            <div class="card-body">
                          <h5 class="card-title">${element.Name}</h5>
                           <p class="card-text">${element.Category}</p>
                            </div>
                    </div>
                            `
        row.appendChild(div)
    });

}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<body>

    <button class="bk" onclick="filterArrayByCategory('bike')">bike</button>
    <button class="clthng" onclick="filterArrayByCategory('clothing')">clothing</button>
    

    <section>
        <div class="container">
            <div class="row">
                
            </div>
        </div>
    </section>





    <script src="script.js"></script>
</body>
</html>

enter image description here

3

Answers


  1. Just add row.innerHTML = ''; to clear row on click:

    const arr = [
      {
        "id": "1",
        "Name": "Coke 500ml",
        "Price": "80",
        "Quantity": "50",
        "Category": "bike"
      },
      {
        "id": "2",
        "Name": "Cake",
        "Price": "150",
        "Quantity": "40",
        "Category": "clothing"
      },
      {
        "id": "3",
        "Name": "Beef Ribs",
        "Price": "100",
        "Quantity": "50",
        "Category": "clothing"
      },
      {
        "id": "4",
        "Name": "Cabbage Salad",
        "Price": "50",
        "Quantity": "30",
        "Category": "clothing"
      },
      {
        "id": "5",
        "Name": "Cake",
        "Price": "150",
        "Quantity": "30",
        "Category": "bike"
      },
      {
        "id": "6",
        "Name": "Beef Ribs",
        "Price": "100",
        "Quantity": "30",
        "Category": "bike"
      }
    ];
    
    const row = document.querySelector('.row')
    
    function filterArrayByCategory(category) {
      row.innerHTML = '';
      const a = arr.filter(el => el.Category === category);
    
      a.map(element => {
        const div = document.createElement('div')
        div.className = 'col-lg-4 col-md-4 col-sm-6 col-12 p-3'
        div.innerHTML = `
          <div class="card" style="width: 18rem; height: 100% ">
            <div class="card-body">
              <h5 class="card-title">${element.Name}</h5>
              <p class="card-text">${element.Category}</p>
            </div>
          </div>
        `
        row.appendChild(div)
      });
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
    </head>
    <body>
    
        <button class="bk" onclick="filterArrayByCategory('bike')">bike</button>
        <button class="clthng" onclick="filterArrayByCategory('clothing')">clothing</button>
        
    
        <section>
            <div class="container">
                <div class="row">
                    
                </div>
            </div>
        </section>
    
    
    
    
    
        <script src="script.js"></script>
    </body>
    </html>
    Login or Signup to reply.
  2. The problem is because you’re appending instead of replacing

    replace that line

        row.appendChild(div);
    

    with

        row.innerHTML = div;
    
    Login or Signup to reply.
  3. 1: use a dataset value with category information
    2: use a class noDisplay to show / hide information with a toggle class method…

    const data = 
      [ { id: '1', Name: 'Coke 500ml',    Price:  '80', Quantity: '50', Category: 'bike'     } 
      , { id: '2', Name: 'Cake',          Price: '150', Quantity: '40', Category: 'clothing' } 
      , { id: '3', Name: 'Beef Ribs',     Price: '100', Quantity: '50', Category: 'clothing' } 
      , { id: '4', Name: 'Cabbage Salad', Price:  '50', Quantity: '30', Category: 'clothing' } 
      , { id: '5', Name: 'Cake',          Price: '150', Quantity: '30', Category: 'bike'     } 
      , { id: '6', Name: 'Beef Ribs',     Price: '100', Quantity: '30', Category: 'bike'     } 
      ];
    
    const row     = document.querySelector('.row');
    const rowElms = data.map( el =>
      {
      let rowElm         = document.createElement('div');
      rowElm.className   = 'col-lg-4 col-md-4 col-sm-6 col-12 p-3';
      rowElm.dataset.cat = el.Category;     // add category as dataset value.
      rowElm.innerHTML   = `
        <div class="card" style="width: 18rem; height: 100% ">
          <div class="card-body">
            <h5 class="card-title">${el.Name}</h5>
            <p class="card-text">${el.Category}</p>
          </div>
        </div>`;
      return row.appendChild(rowElm);  // map return value is DOM element
      })
    
    function filterArrayByCategory(cat)
      {
      let isAll = (cat==='*' )
    
      rowElms.forEach(elm => elm.classList.toggle('noDisplay', !(elm.dataset.cat===cat || isAll)));
      }
    .noDisplay { display : none; }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
    
    
    <button onclick="filterArrayByCategory('*')"        > All      </button>
    <button onclick="filterArrayByCategory('bike')"     > bike     </button>
    <button onclick="filterArrayByCategory('clothing')" > clothing </button>
    
    
    <section>
      <div class="container">
        <div class="row"></div>
      </div>
    </section>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search