Home » Php » php – Multiple checkbox selection (filter) for products

php – Multiple checkbox selection (filter) for products

Posted by: admin July 12, 2020 Leave a comment

Questions:

What I’m trying to do is to make a filter for products, I’m retrieving products from the database including an image and some information, and I want some filters like: PRODUCT and BRAND

I have this code but when I select two filters like brand 1 + product 2 that shows me all products of brand 1 and all products number 2.. and I want it combined…

Here’s my code:

HTML+PHP

<div id="row" class="row">

<?php

if(!empty($_GET["category"])){
  include('open_conexion.php');
  $sql = "SELECT * FROM products WHERE category='".$_GET["category"]."'";

  $result = mysql_query($sql);

  while ($row = mysql_fetch_array($result)) {

  ?>

  <div class="col-lg-4"  data-category="<?php echo $row['product'];?>" brand="<?php echo $row['brand'];?>" >
      <img  class="img-circle" src='images/<?php echo $row['imag']; ?>'  width="180px;" height="180px;"alt="">
      <h4><?php echo $row['product']." ". $row['brand']; ?></h4>
      <p><?php echo $row['description'];?> </p>
      <p><a class="btn btn-default" href='detalles.php?id=<?php echo $row['id_product']?>'>View Details &raquo;</a></p>

</div><!-- /.col-lg-4 -->



  <?php } } ?>


  </div><!-- /.row -->

and the jQuery:

 <script>
$('input[type="checkbox"]').click(function() {
if ($('input[type="checkbox"]:checked').length > 0) {
    $('.row >div').hide();


    $('input[type="checkbox"]:checked').each(function() {
        $('.row >div[data-category=' + this.value + ']').show();
        $('.row >div[brand=' + this.value + ']' ).show();

    });
} else {
    $('.row >div').show();


}
});

Thanks

How to&Answers:

I assume that you are trying to filter the products client side using jquery or javascript and not with server side with queries.

Keep your checkboxes and products list as shown below:

<div><input name="product1" id="product1" data-id="1" class="products" type="checkbox" />Product 1</div>
<div><input name="product2" id="product2" data-id="2" class="products" type="checkbox" />Product 2</div>
<div><input name="product3" id="product3" data-id="3" class="products" type="checkbox" />Product 3</div>
<div><input name="brand1" id="brand1" data-id="1" class="brands" type="checkbox" />Brand 1</div>
<div><input name="brand2" id="brand2" data-id="2" class="brands" type="checkbox" />Brand 2</div>
<div><input name="brand3" id="brand3" data-id="3" class="brands" type="checkbox" />Brand 3</div>
<div class="row">
    <div class="product" brand="1" data-category="1">product 1 brand 1</div>
    <div class="product" brand="1" data-category="1">product 1 brand 1</div>
    <div class="product" brand="2" data-category="1">product 1 brand 2</div>
    <div class="product" brand="2" data-category="1">product 1 brand 2</div>
    <div class="product" brand="3" data-category="1">product 1 brand 3</div>
    <div class="product" brand="3" data-category="1">product 1 brand 3</div>

    <div class="product" brand="1" data-category="2">product 2 brand 1</div>
    <div class="product" brand="1" data-category="2">product 2 brand 1</div>
    <div class="product" brand="2" data-category="2">product 2 brand 2</div>
    <div class="product" brand="2" data-category="2">product 2 brand 2</div>
    <div class="product" brand="3" data-category="2">product 2 brand 3</div>
    <div class="product" brand="3" data-category="2">product 2 brand 3</div>

    <div class="product" brand="1" data-category="3">product 3 brand 1</div>
    <div class="product" brand="1" data-category="3">product 3 brand 1</div>
    <div class="product" brand="2" data-category="3">product 3 brand 2</div>
    <div class="product" brand="2" data-category="3">product 3 brand 2</div>
    <div class="product" brand="3" data-category="3">product 3 brand 3</div>
    <div class="product" brand="3" data-category="3">product 3 brand 3</div>
</div>

Javascript code should be like this, i have used jQuery for filtering. Hope you are also trying with jQuery.

<script type="text/javascript">
$(function(){
    $('.products, .brands').on('click', function(){
        var checkedProducts = $('.products:checked');
        var checkedBrands = $('.brands:checked');
        if(checkedProducts.length || checkedBrands.length){
            if(checkedBrands.length === 0){
                $('.row > div').hide();
                $.each(checkedProducts, function(){
                    var prdId = $(this).attr('data-id');
                    $('.row > div[data-category="' + prdId + '"]').show();
                });
            } else if(checkedProducts.length === 0) {
                $('.row > div').hide();
                $.each(checkedBrands, function(){
                    var brandId = $(this).attr('data-id');
                    $('.row > div[brand="' + brandId + '"]').show();
                });
            } else {
                $('.row > div').hide();
                $.each(checkedProducts, function(){
                    var prdId = $(this).attr('data-id');
                    $.each(checkedBrands, function(){
                        var brandId = $(this).attr('data-id');
                        $('.row > div[data-category="' + prdId + '"][brand="' + brandId + '"]').show();
                    });
                });
            }
        } else {
            $('.row > div').show();
        }
    });
});
</script>

Thats it! You’re saved.. Let me know if you have any issues.

Answer:

Most problematic lines of your code (concerning filtering) are probably these two:

$('.row >div[data-category=' + this.value + ']').show();
$('.row >div[brand=' + this.value + ']' ).show();

Here you explicitly say “show all divs where data-category=value and show all divs where brand=value“.

What you actually want is “show all divs where data-category=value and brand=value“.

You may want to try something like

$('input[type="checkbox"]:checked').each(function() {
    $('.row >div[data-category=' + this.value + '][brand=' + this.value + ']').show();    
});

Also, some extra gotchas in your code (not relevant to your filtering problem):

1) Really straight-forward sql injection possibility at

$sql = "SELECT * FROM products WHERE category='".$_GET["category"]."'";

2) You bind click event to every checkbox in your DOM, even to checkboxes that are not meant for filtering, also it would be more appropriate to use change event instead of click event (you can also change checkbox state via keyboard, not only by mouse click)

$('input[type="checkbox"]').click(function() {

Answer:

If I understand your question correctly, what you need to do is enhance your $sql statement so that you are only pulling the data the report needs:

$sql='SELECT * FROM products'; // Pull everything by default
if (isset($_GET['category']) || isset($_GET['product'])) { //Only need the following if something was checked
    $sql.=' WHERE ';
    if (isset($_GET['category'])) {
        $sql.='category="' . $_GET['category'] . '"'; //Narrows down the results
      if (isset($_GET['product'])) {
          $sql.=' AND '; //Only necessary if both are checked
      }
    }
    if (isset($_GET['product'])) {
        $sql.='product="' . $_GET['product'] . '"'; //Narrows down the results...more if both were checked
    }
}

If you are only running this when something is checked, the first conditional isn’t necessary, though I am pretty sure that won’t be the case.

Answer:

Let’s be simple here.

Instead of hiding all, and then just showing some, show all and then hide the ones that DON’T match.

// Show all at the beginning
$('.row >div').show();

// For each item...
$('.row > div ).each(function(){
    var $item = $(this);

    // Check against each checkbox...
    $('input[type="checkbox"]:checked').each(function() {
        var $checkbox = $(this), pass = false;
        if($item.attr('data-category') == $checkbox.value) pass = true;
        if($item.attr('brand') == $checkbox.value) pass = true;

        // and if the brand or category doesn't match the checkbox value, hide it

        if(!pass) $item.hide();

    });
});