Jump to content

[SOLVED]Price Range filtering in Front end using processwire


Batyr
 Share

Recommended Posts

Hi Guys, Recently I was working on my new project and I need to implement price range filtering. I am using noUiSlider which came with the template that I have purchased. How can I pass values of minimum and maximum values using ajax? I am using foreach loop as shown in code in the code

<ul class="row shop list-unstyled" id="grid">
                    <!-- product -->
                    <?php $result = $pages->get("/sadakalar")->children();?>
                    <?php foreach ($result as $r): ?>
                        <li class="col-sm-4 col-md-3 col-lg-3 product m-product" data-groups='["bedroom"]'>
                            <div class="img-bg-color primary">
                                <h5 class="product-price" data-price="<?=$r->price;?>"><?=$r->price_range->max;?> manat</h5>
                                <a href="<?=$r->url;?>" class="product-link"></a>
                                <!-- / product-link -->
                                <img src="<?=$r->image->first()->url;?>" alt="<?=$r->image->description;?>">
                                <!-- / product-image -->

                                <!-- product-hover-tools -->
                                <div class="product-hover-tools">
                                    <a href="<?=$r->url;?>" class="view-btn" data-toggle="tooltip" title="Giňişleýin gör">
                                        <i class="lnr lnr-eye"></i>
                                    </a>
                                    <!--<a href="shopping-cart.html" class="cart-btn" data-toggle="tooltip" title="Add to Cart">
                                        <i class="lnr lnr-cart"></i>
                                    </a>-->
                                </div><!-- / product-hover-tools -->

                                <!-- product-details -->
                                <div class="product-details">
                                    <h5 class="product-title"><?=$r->title;?></h5>
                                    <!--<p class="product-category">Hemme zat içinde</p>-->
                                </div><!-- / product-details -->
                            </div><!-- / img-bg-color -->
                        </li>
                    <!-- / product -->
                    <?php endforeach; ?>
                    <!-- sizer -->
                    <li class="col-sm-4 col-md-3 col-lg-6 shuffle_sizer"></li>
                    <!-- / sizer -->

                </ul> <!-- / products -->

Here is the code of my range slider: Values of min and max values are stored inside of <span>

<!-- filter-by-price widget -->
                <div class="widget">
                    <h5 class="widget-title">Baha boýunça saýhalla</h5>

                    <div id="range-slider" class="noUi-target noUi-rtl noUi-horizontal">
                    </div><!-- / range-slider -->

                    <div class="range-filter">
                        <div class="column filter-button">
                            <button type="submit" class="btn btn-xs btn-default-filled btn-rounded" id="filter">Saýhalla</button>
                        </div> <!--/ filter-button -->
                        <div class="column range-values">
                            <p>$<span class="value" id="range-slider-value-min"></span> - $<span class="value" id="range-slider-value-max"></span></p>
                        </div><!-- / range-values -->
                    </div><!-- / range-filter -->
                    <!-- / filter-by-price widget -->

And lastly here is my javascript of which handles the changes in noUiSlider:

<script>
var limitSlider = document.getElementById('range-slider');

noUiSlider.create(limitSlider, {
    start: [ 100, 5000 ],
    limit: 10000,
    behaviour: 'drag',
    connect: true,
    range: {
        'min': 0,
        'max': 10000
    }
});

var limitFieldMin = document.getElementById('range-slider-value-min');
var limitFieldMax = document.getElementById('range-slider-value-max');
var dataString = limitFieldMin + limitFieldMax;

limitSlider.noUiSlider.on('update', function( values, handle ){
    (handle ? limitFieldMax : limitFieldMin).innerHTML = values[handle];
});

</script>

So what I want to do is, whenever user slides the range filter, it automatically throws the filtered products. I have also attached the picture of my website. Any help is greatly appreciated. Thank you in advance!

Снимок.PNG

Edited by Batyr
I found the way to do it.
Link to comment
Share on other sites

To get you started, I give you an example of an ajax request triggered by a noUiSlider's event which update the markup.

Do not hesitate to ask if you don't understand something.

 

Javascript code :

// slider element
var slider = document.getElementById('noUiSlider');
// create the slider object
noUiSlider.create(slider, {
    start: [0, 100],
    step: 1, // avoid float values
    range: {
        'min': 0,
        'max': 100
    }
});
    
// change the value when noUiSlider values are updated
slider.noUiSlider.on('update', function( values, handle ) {
    if ( handle ) {
    	$("#noUiSlider-data").data("max", values[handle]);
    } else {
    	$("#noUiSlider-data").data("min", values[handle]);
    }
});

// on event 'set' send ajax request
slider.noUiSlider.on('set', function( values, handle ) {
    // get the min and max from the data attribute of #noUiSlider-data
    $data = {min: $("#noUiSlider-data").data("min"), max: $("#noUiSlider-data").data("max")};
    // ajax request
    $.ajax({
    	url: $(this).data('url'), // url from the data attribute of #noUiSlider
    	type: "post",
	data: $data
  	}).done(function (response, textStatus, jqXHR) {
		$('#list').html(response); // write markup to #list element
  	})
});

 

PHP code  :

<?php namespace ProcessWire;

$list = '';
$limit = 100;
if(isset($input->post->min) && isset($input->post->max)) {
    $min = $input->post->min; // don't forget to sanitize
    $max = $input->post->max; // don't forget to sanitize
    $li = '';
    $products = $pages->find("template=product, start=$min, limit=$max"); // let assume there is a template 'product'
    foreach ($products as $product) {
        $li .= "<li>". $product->title . "</li>";
    }
    $list = "<ol>$li</ol>";
    echo $list;
}
?>

 

HTML Markup :


<div id="noUiSlider" data-url="<?= $page->url; ?>"></div>
<span id="noUiSlider-data"></span>
<div id="list">
    <?= $list ?>
</div>

#noUiSlider is the slider element

#noUiSlider-data will contain values changed from the #uiSlider element

#list is the element updated by the ajax response

 

enjoy

 

nouislider.gif.1fcce3ae6c26f55826df674de7905023.gif

Edited by flydev
screenshot
  • Like 11
Link to comment
Share on other sites

Hi @flydev Thank you, this is indeed a great solution. But for my case I used another tactic, using the search technique, so my PHP code looks like this:

<ul class="row shop list-unstyled" id="grid">
                    <?php 
                         // search.php template file
                        // look for a GET variables named 'min', 'max' and sanitize it
                        $min = $sanitizer->text($input->get->min); 
                        $max = $sanitizer->text($input->get->max);

                        
                          // did $min and $max have anything in it?
                        
                            if($min and $max){ 
                              // Send our sanitized query 'min', 'max' variable to the whitelist where it will be
                              // picked up and echoed in the search box by _main.php file. Now we could just use
                              // another variable initialized in _init.php for this, but it's a best practice
                              // to use this whitelist since it can be read by other modules. That becomes 
                              // valuable when it comes to things like pagination. 
                              $input->whitelist('min', $min); 
                              $input->whitelist('max', $max);
                              // Sanitize for placement within a selector string. This is important for any 
                              // values that you plan to bundle in a selector string like we are doing here.
                              $min = $sanitizer->selectorValue($min);
                              $max = $sanitizer->selectorValue($max);
                              // Search the title and body fields for our query text.
                              $selector = "price>=$min , price<=$max"; 
                              //if($user->isLoggedin()) $selector .= ", has_parent!=2"; 
                              // Find pages that match the selector
                              $items = $pages->find($selector); 
                              // did we find any matches?
                                  if($items->count) {
                                  $count = "Görkezilen baha boýunça jemi $items->count sanysy tapyldy";
                    ?>
                    <!-- product -->
                    <p class="shop-results space-left"><strong><?=$count;?></strong> </p>
                    <?php foreach ($items as $match): ?>
                        <li class="col-sm-6 col-md-3 col-lg-3 product m-product" data-groups='["bedroom"]'>
                            <div class="img-bg-color primary">
                                <h5 class="product-price"><?=$match->price;?> manat</h5>
                                <a href="<?=$r->url;?>" class="product-link"></a>
                                <!-- / product-link -->
                                <img src="<?=$match->image->first()->url;?>" alt="<?=$match->image->description;?>">
                                <!-- / product-image -->

                                <!-- product-hover-tools -->
                                <div class="product-hover-tools">
                                    <a href="<?=$match->url;?>" class="view-btn" data-toggle="tooltip" title="Giňişleýin gör">
                                        <i class="lnr lnr-eye"></i>
                                    </a>
                                    <!--<a href="shopping-cart.html" class="cart-btn" data-toggle="tooltip" title="Add to Cart">
                                        <i class="lnr lnr-cart"></i>
                                    </a>-->
                                </div><!-- / product-hover-tools -->

                                <!-- product-details -->
                                <div class="product-details">
                                    <h5 class="product-title"><?=$match->title;?></h5>
                                    <!--<p class="product-category">Hemme zat içinde</p>-->
                                </div><!-- / product-details -->
                            </div><!-- / img-bg-color -->
                        </li>
                    <!-- / product -->
                    <?php endforeach; } } else { ?>
                    <!-- product -->    
                    <?php foreach ($result = $page->children() as $r): ?>
                        <li class="col-sm-6 col-md-3 col-lg-3 product m-product" data-groups='["bedroom"]'>
                            <div class="img-bg-color primary">
                                <h5 class="product-price"><?=$r->price;?> manat</h5>
                                <a href="<?=$r->url;?>" class="product-link"></a>
                                <!-- / product-link -->
                                <img src="<?=$r->image->first()->url;?>" alt="<?=$r->image->description;?>">
                                <!-- / product-image -->

                                <!-- product-hover-tools -->
                                <div class="product-hover-tools">
                                    <a href="<?=$r->url;?>" class="view-btn" data-toggle="tooltip" title="Giňişleýin gör">
                                        <i class="lnr lnr-eye"></i>
                                    </a>
                                    <!--<a href="shopping-cart.html" class="cart-btn" data-toggle="tooltip" title="Add to Cart">
                                        <i class="lnr lnr-cart"></i>
                                    </a>-->
                                </div><!-- / product-hover-tools -->

                                <!-- product-details -->
                                <div class="product-details">
                                    <h5 class="product-title"><?=$r->title;?></h5>
                                    <!--<p class="product-category">Hemme zat içinde</p>-->
                                </div><!-- / product-details -->
                            </div><!-- / img-bg-color -->
                        </li>
                    <!-- / product -->
                    <?php endforeach; 
                     }?>
                    <!-- sizer -->
                    <li class="col-sm-6 col-md-3 col-lg-3 shuffle_sizer"></li>
                    <!-- / sizer -->

                </ul> <!-- / products -->

and Javascript:

var limitSlider = document.getElementById('range-slider');

noUiSlider.create(limitSlider, {
    start: [ 0, 10000 ],
    step: 1,
    behaviour: 'drag',
    connect: true,
    range: {
        'min': 0,
        'max': 10000
    }
});


 var limitFieldMin = document.getElementById('range-slider-value-min');
 var limitFieldMax = document.getElementById('range-slider-value-max');

limitSlider.noUiSlider.on('update', function( values, handle ){
    (handle ? limitFieldMax : limitFieldMin).value = values[handle];
});   

The range filter area in my page is:

<div class="range-filter">
                        <form action="<?php echo $pages->get('template=shop-right')->url;?>" method='get'>
                            <div class="column filter-button">
                                <button type="submit" class="btn btn-xs btn-default-filled btn-rounded">Saýhalla</button>
                            </div> <!--/ filter-button -->
                            <div class="column range-values">
                                <input type="text" class="value" name="min" size="6" id="range-slider-value-min" value="">
                                <input type="text" class="value" name="max" size="6" id="range-slider-value-max" value="">
                            </div><!-- / range-values -->
                        </form>
</div><!-- / range-filter -->

So whenever I press button 'sort' which is 'sayhalla' in my example, all the values are posted and results are returned as a result. Your case is super as well, it works perfectly but for my template it is better to implement it this way. I tried to implement yours too, but no success. Thank you again!

  • Like 4
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...