Home > Blockchain >  cant hide HTML elements with JavaScript
cant hide HTML elements with JavaScript

Time:03-12

i'm trying to build a filter/search buttons using pure JavaScript. the idea is simple at least in my mind , you click a type and all the other types will be set to (hide) will the ones you want remain .

the javascript code is as follows

const btns = document.querySelectorAll('.btn');
const storeProducts = document.querySelectorAll('.article-card');


for (i = 0; i < btns.length; i  ) {

    btns[i].addEventListener('click', (e) => {
        e.preventDefault()
        
        const filter = e.target.dataset.filter;
        console.log(filter);
        console.table(storeProducts);
        
        storeProducts.forEach((product)=> {
            if (filter === 'all'){
                product.style.display = 'block'
            } else {
                if (product.classList.contains(filter)){
                    product.style.display = 'block'
                } else {
                    product.style.display = 'none'
                }
            }
        });
    });
};

the HTML content is coming from mysql database , and it gets looped to print the element the element is as follows

print '


<article style="display:block;" >
<div >
    <a href="#" >' . $row['special'] . '</a>
    <h3 >' . $row['name'] . '</h3>
    <p >some notes here</p>
    <div >
</article> ';

the filter buttons

<div >
    <a href="#"  data-filter="all">All</a>
    <a href="#"  data-filter="type1">type1</a>
    <a href="#"  data-filter="type2">type2</a>
    <a href="#"  data-filter="type3">type3</a>
    <a href="#"  data-filter="type4">type4</a>
   </div>

the buttons i press do absolutely nothing except for the values to show in the console , also i would like to point out this console.table shows nothing

console.table(storeProducts);

EDIT : problem solved !!! actually the script was OK but the browser was just running a cached version of the script , so it didn't work as intended but after clearing the cache now it works perfectly .

CodePudding user response:

without seeing your code and how data is being populated, I can not be too sure, but are you including the script before fetching the database (in the html file). It'll be much more helpful if you could provide us with a sample populated html file.

CodePudding user response:

I suspect the error is at this point. You check if the filter word is contained in the ClassList. But you get the filter word from the data attribute data-filter. So I guess you have to look there as well.

if (product.dataset.filter.contains(filter)){

In my example i generate the products by javascript. I saw you generate serverside. But it doesn't really matter here because the function works for both.

working exammple

let products = {
  data: [
    {
      productName: "Regular White T-Shirt",
      category: "Topwear",
      price: "30",
      image: "https://via.placeholder.com/400",
    },
    {
      productName: "Beige Short Skirt",
      category: "Bottomwear",
      price: "49",
      image: "https://via.placeholder.com/400",
    },
    {
      productName: "Sporty SmartWatch",
      category: "Watch",
      price: "99",
      image: "https://via.placeholder.com/400",
    },
    {
      productName: "Basic Knitted Top",
      category: "Topwear",
      price: "29",
      image: "https://via.placeholder.com/400",
    },
    {
      productName: "Black Leather Jacket",
      category: "Jacket",
      price: "129",
      image: "https://via.placeholder.com/400",
    },
    {
      productName: "Stylish Pink Trousers",
      category: "Bottomwear",
      price: "89",
      image: "https://via.placeholder.com/400",
    },
    {
      productName: "Brown Men's Jacket",
      category: "Jacket",
      price: "189",
      image: "https://via.placeholder.com/400",
    },
    {
      productName: "Comfy Gray Pants",
      category: "Bottomwear",
      price: "49",
      image: "https://via.placeholder.com/400",
    },
  ],
};

for (let i of products.data) {
  //Create Card
  let card = document.createElement("div");
  //Card should have category and should stay hidden initially
  card.classList.add("card", i.category, "hide");
  //image div
  let imgContainer = document.createElement("div");
  imgContainer.classList.add("image-container");
  
  // dataSet
  let dataSet = card.setAttribute('data-filter', i.category);
  
  //img tag
  let image = document.createElement("img");
  image.setAttribute("src", i.image);
  imgContainer.appendChild(image);
  card.appendChild(imgContainer);
  //container
  let container = document.createElement("div");
  container.classList.add("container");
  //product name
  let name = document.createElement("h5");
  name.classList.add("product-name");
  name.innerText = i.productName.toUpperCase();
  container.appendChild(name);
  //price
  let price = document.createElement("h6");
  price.innerText = "$"   i.price;
  container.appendChild(price);

  card.appendChild(container);
  document.getElementById("products").appendChild(card);
}


//parameter passed from button (Parameter same as category)
function filterProduct(value) {
  //Button class code
  let buttons = document.querySelectorAll(".button-value");
  buttons.forEach((button) => {
    //check if value equals innerText
    if (value.toUpperCase() == button.innerText.toUpperCase()) {
      button.classList.add("active");
    } else {
      button.classList.remove("active");
    }
  });

  //select all cards
  let elements = document.querySelectorAll(".card");
  //loop through all cards
  elements.forEach((element) => {
    //display all cards on 'all' button click
    if (value == "all") {
      // element.classList.remove("hide");
      element.classList.remove("hide");
    } else {
      //Check if element contains category class      
      if (element.getAttribute('data-filter') == value) {
        //display element based on category
        element.classList.remove("hide");
      } else {
        //hide other elements
        element.classList.add("hide");
      }
    }
  });
}


//Initially display all products
window.onload = () => {
  filterProduct("all");
};
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  border: none;
  outline: none;
  font-family: "Poppins", sans-serif;
}
body {
  background-color: #f5f8ff;
}
.wrapper {
  width: 95%;
  margin: 0 auto;
}
#buttons {
  margin-top: 30px;
  text-align: center;
}
.button-value {
  border: 2px solid #6759ff;
  padding: 1em 2.2em;
  border-radius: 3em;
  background-color: transparent;
  color: #6759ff;
  cursor: pointer;
}
.active {
  background-color: #6759ff;
  color: #ffffff;
}
#products {
  display: grid;
  grid-template-columns: auto auto auto;
  grid-column-gap: 1.5em;
  padding: 2em 0;
}
.card {
  background-color: #ffffff;
  max-width: 18em;
  margin-top: 1em;
  padding: 1em;
  border-radius: 5px;
  box-shadow: 1em 2em 2.5em rgba(1, 2, 68, 0.08);
}
.image-container {
  text-align: center;
}
img {
  max-width: 100%;
  object-fit: contain;
  height: 15em;
}
.container {
  padding-top: 1em;
  color: #110f29;
}
.container h5 {
  font-weight: 500;
}
.hide {
  display: none;
}
@media screen and (max-width: 720px) {
  img {
    max-width: 100%;
    object-fit: contain;
    height: 10em;
  }
  .card {
    max-width: 10em;
    margin-top: 1em;
  }
  #products {
    grid-template-columns: auto auto;
    grid-column-gap: 1em;
  }
}
    <div >

      <div id="buttons">
        <button  onclick="filterProduct('all')">All</button>
        <button  onclick="filterProduct('Topwear')">
          Topwear
        </button>
        <button  onclick="filterProduct('Bottomwear')">
          Bottomwear
        </button>
        <button  onclick="filterProduct('Jacket')">
          Jacket
        </button>
        <button  onclick="filterProduct('Watch')">
          Watch
        </button>
      </div>
      <div id="products"></div>
    </div>

CodePudding user response:

Mind Using CSS? If yes I can make a solution for you.

  • Related