JS простой фильтр для товаров магазина

#javascript #filter #shop

#javascript

Вопрос:

    <div class="col-lg-3 col-md-6 shopItem Yellow XL Puma">
          <div class="products-item ">
            <div class="product-img">
              <img class='img-fluid' src="img/kamizelka2.jpg" alt="kamizelka zółta">
              <div class="overlay">
                <a href="" class="btn mybtn1">Kup teraz</a>
              </div>
            </div>
            <div class="product-content">
              <div class="product-price">
                <span class="new-price">11zł</span>
                <span class="old-price">23zł</span>
              </div>
              <h5 class='product-name'>Kamizelka Dwa</h5>
            </div>
          </div>
        </div> 

У меня проблема, которую мне трудно объяснить.
Я попытался создать этот простой фильтр для товаров магазина.
В настоящее время эта функция принимает только один последний выбранный вариант (я имею в виду, что я не могу найти зеленый xl Adidas, но только один из этих вариантов, которые меняются при использовании назначенного элемента выбора.
Есть идеи, как это исправить?

 function filterAction () {
    const types = document.querySelectorAll('.form-control');
    const storeProducts = document.querySelectorAll('.shopItem');
   
    types.forEach((type)=>{
        type.addEventListener('change',(e)=>{ 
            storeProducts.forEach((product)=> {
             product.style.display='none';
                if(type.value =="All" ) {
                    product.style.display ="block"
             
                } else {
                    if (product.classList.contains(type.value)) {   
            
                        product.style.display = 'block'               
                    } else {
                        product.style.display = "none"
                    }
                }
            })
        })
    })
}
filterAction(); 
  <div class="search-item d-flex text-center">
            <div class="form-group col-sm-4">
              <label for="exampleFormControlSelect1">Color</label>
              <select class="form-control" id="colorLabel">
                <option data-filter="all">All</option>
                <option data-filter="yellow">Yellow</option>
                <option data-filter="green">Green</option>
                <option data-filter="orange">Orange</option>

              </select>
            </div>
            <div class="form-group col-sm-4">
              <label for="exampleFormControlSelect1">Size</label>
              <select class="form-control" id="exampleFormControlSelect1">
                <option data-filter="all">All</option>
                <option data-filter="s">S</option>
                <option data-filter="m">M</option>
                <option data-filter="l">L</option>
                <option data-filter="xl">XL</option>

              </select>
            </div>
            <div class="form-group col-sm-4">
              <label for="exampleFormControlSelect1">Brand</label>
              <select class="form-control" id="exampleFormControlSelect1">
                <option data-filter="all">All</option>
                <option class='options' data-filter="adidas">Adidas</option>
                <option class='options' data-filter="puma">Puma</option>
                <option class='options' data-filter="gucci">Gucci</option>

              </select>
            </div>
          </div>
  

<!-- begin snippet: js hide: false console: true babel: false -->



  

Комментарии:

1. Пожалуйста, не могли бы вы поделиться кодом с .shopItem товарами?

2. просто поделился 🙂 @Lucius

Ответ №1:

В вашем коде есть некоторые недостатки, если вы выберете какой-либо фильтр, вернетесь к предыдущему и выберите «Все», будет отображен весь магазин, даже если фильтры говорят «нет». Конечно, есть много способов создать фильтр с помощью ванильного JavaScript (и некоторые с помощью jQuery тоже), я сделал один, пытаясь не изменять большую часть вашего кода.

Во-первых, измените HTML-код вашего продукта и добавьте атрибут данных к каждому фильтру, потому что использование class к нему может быть немного запутанным:

 <div class="shopItem" data-color="green" data-size="xl" data-brand="adidas">
    <div class="products-item ">
      <div class="product-img">
        <div class="overlay">
          <a href="" class="btn mybtn1">Green XL Adidas</a>
        </div>
      </div>
      <div class="product-content">
        <h5 class='product-name'>Green XL Adidas</h5>
      </div>
    </div>
</div>
 

У нас будет диктант со всеми вашими текущими пожеланиями по фильтрации:

 const appliedFilters = {};
 

Он будет заполняться каждый раз при изменении фильтра, как:

 {
  size: "S",
  color: "All",
  brand: "Puma"
}
 

И, наконец, filterAction функция:

 function filterAction () {
  const types = document.querySelectorAll('.form-control');
  const storeProducts = document.querySelectorAll('.shopItem');
  const appliedFilters = {};
  types.forEach((type)=>{
    type.addEventListener('change', function(e) { 
      appliedFilters[this.id] = this.value;
      console.log(appliedFilters);
      storeProducts.forEach(function(product) {
        let canShow = true;
        // Iterate all applied filters to determine if the product can be displayed or not
        Object.keys(appliedFilters).forEach(function (key) {
          // If it is 'All' option, we still can display the product
          if (appliedFilters[key].toLowerCase() !== 'all' amp;amp; product.getAttribute('data-'   key).toLowerCase() !== appliedFilters[key].toLowerCase()) {
            canShow = false;
          }
        })
        if (canShow) {
          product.style.display = 'block';
        }else{
          product.style.display = 'none';
        }
      })
    })
  })
}
 

ДЕМОНСТРАЦИЯ:

 function filterAction() {
  const types = document.querySelectorAll('.form-control');
  const storeProducts = document.querySelectorAll('.shopItem');
  const appliedFilters = {};
  types.forEach((type) => {
    type.addEventListener('change', function(e) {
      appliedFilters[this.id] = this.value;
      console.log(appliedFilters);
      storeProducts.forEach(function(product) {
        let canShow = true;
        // Iterate all applied filters to determine if the product can be displayed or not
        Object.keys(appliedFilters).forEach(function(key) {
          // If it is 'All' option, we still can display the product
          if (appliedFilters[key].toLowerCase() !== 'all' amp;amp; product.getAttribute('data-'   key).toLowerCase() !== appliedFilters[key].toLowerCase()) {
            canShow = false;
          }
        })
        if (canShow) {
          product.style.display = 'block';
        } else {
          product.style.display = 'none';
        }
      })
    })
  })
}
filterAction(); 
 .search-item {
  margin-bottom: 10px;
} 
 <div class="search-item d-flex text-center">
  <div class="form-group col-sm-4">
    <label for="exampleFormControlSelect1">Color</label>
    <select class="form-control" id="color">
      <option data-filter="all">All</option>
      <option data-filter="yellow">Yellow</option>
      <option data-filter="green">Green</option>
      <option data-filter="orange">Orange</option>

    </select>
  </div>
  <div class="form-group col-sm-4">
    <label for="exampleFormControlSelect1">Size</label>
    <select class="form-control" id="size">
      <option data-filter="all">All</option>
      <option data-filter="s">S</option>
      <option data-filter="m">M</option>
      <option data-filter="l">L</option>
      <option data-filter="xl">XL</option>

    </select>
  </div>
  <div class="form-group col-sm-4">
    <label for="exampleFormControlSelect1">Brand</label>
    <select class="form-control" id="brand">
      <option data-filter="all">All</option>
      <option class='options' data-filter="adidas">Adidas</option>
      <option class='options' data-filter="puma">Puma</option>
      <option class='options' data-filter="gucci">Gucci</option>

    </select>
  </div>
</div>

<div class="shopItem" data-color="green" data-size="s" data-brand="puma">
  <div class="products-item ">
    <div class="product-img">
      <div class="overlay">
        <a href="" class="btn mybtn1">Green S Puma</a>
      </div>
    </div>
    <div class="product-content">
      <h5 class='product-name'>Green S Puma</h5>
    </div>
  </div>
</div>

<div class="shopItem" data-color="green" data-size="xl" data-brand="adidas">
  <div class="products-item ">
    <div class="product-img">
      <div class="overlay">
        <a href="" class="btn mybtn1">Green XL Adidas</a>
      </div>
    </div>
    <div class="product-content">
      <h5 class='product-name'>Green XL Adidas</h5>
    </div>
  </div>
</div>