Batyr

[SOLVED]Price Range filtering in Front end using processwire

Recommended Posts

Posted (edited)

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.

Share this post


Link to post
Share on other sites
Posted (edited)

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 10

Share this post


Link to post
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 3

Share this post


Link to post
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


  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Pete Jones
      We have a big selector which we have broken down into 3 chunks to return a list of notes (pages) with repeaters as follows. We also allow the user to filter the results. The problem we have is that the page currently takes nearly 10 seconds to process results. Is there anything we can do to improve the performance of this? I wonder if it would be worth bringing the filters into each of the find()s. I assume that caching here wouldn't work due to querystring parameters?
      $selector = "template=horse-note"; // Notes with unread comments (date order, most recent first) $notes_with_unread_comments = $pages->find("{$selector}, h_notes_comments.count>0, h_notes_comments.{$session->unread_by}>0, sort=h_notes_last_comment"); //echo 'Notes with unread comments ('.count($notes_with_unread_comments).'):<br />'.$notes_with_unread_comments.'<br /><br />'; // Unread notes (date order, most recent first) $notes_unread = $pages->find("{$selector}, {$session->unread_by}>0, sort=h_notes_last_comment"); //echo 'Notes unread ('.count($notes_unread).'):<br />'.$notes_unread.'<br /><br />'; // Read notes in date order (most recent first) that they were either added or that the last comment was made, whichever is most recent. $notes_other = $pages->find("{$selector}, sort=-h_notes_last_comment"); //echo 'Notes other ('.count($notes_other).'):<br />'.$notes_other.'<br /><br />'; // create notes PageArray $notes_total = new PageArray(); $notes_total->add($notes_other); $notes_total->prepend($notes_unread); $notes_total->prepend($notes_with_unread_comments); // FILTER // sanitize inputs $horse = $sanitizer->text($input->get->horse); $category = $sanitizer->int($input->get->category); $from_date = $sanitizer->text($input->get->from_date); $to_date = $sanitizer->text($input->get->to_date); $comments = $sanitizer->int($input->get->comments); // horse name if($horse) { $selector .= ", parent.h_name%=$horse"; } // note category if($category) { $selector .= ", h_notes_category_id=$category"; } // from date if($from_date) { $selector .= ", h_notes_last_comment>=".strtotime("$from_date 00:00:00"); } // to date if($to_date) { $selector .= ", h_notes_last_comment<=".strtotime("$to_date 23:59:59"); } // comments if($comments) { $selector .= ", h_notes_comments.count>0"; } // apply filter if($selector!='template=horse-note') { $notes_total = $notes_total->find($selector); } // slice PageArray according to pageNum $pageNum = $input->pageNum; $limit = 15; $start = ($pageNum-1)*$limit; $notes = $notes_total->slice($start, $limit);
    • By luckybusted
      Hey guys its me again,
      I'm looking for a solution to show a List of Pages that have the same value in "fieldset-x" as the current Pages "title" e.g. .
      My hardcoded Solution looks like this:
      <?php                              $homepage = $pages->get("/stores/");                 $stores = $homepage->children("location_category=1065, city=1010");                 $children = $stores->getRandom(2);                              foreach($children as $child){                 ... echo ...                 }             ?>  
      Now I need to check the title of the current page "{$page->title}" and check if it is equal to the value of fieldset "city" of a child Page of "Stores" ...
      Any ideas?
    • By onjegolders
      I've been reading up on a few posts on categories but I'm struggling to get them working.
      I saw a video from PW1
      and the example seems nice and simple:Output the categories, click one and the list of entries gets filtered.
      I tried to replicate that but no joy. I can't seem to understand how Ryan can output $page->categories from his page when really the categories are surely part of children()?
      Is it really possible to filter categories of events or news this simply? I've seen other examples in the forums which look much more complex (urlSegments and the like).
      I currently have my category page set up as a child of home, and categories as its children.
      Before seeing that video, I had managed to output the categories like this:
      <div id="events_index_side"> <?php if ($pages->find("template=category")) { ?> <div class="events_index_side_box"> <h5 class="page_header">By category</h5> <ul> <?php $categories = $pages->find("template=category"); foreach ($categories as $category) { ?> <li><a href="<?php echo $page->url . $category->name; ?>"><?php echo $category->title; ?></a></li> <?php } ?> </ul> </div><!-- /.events_index_side_box --> <?php } ?> but using this method, I'm not quite sure how I can get the page to reload with just those categorised entries?
      Would appreciate if anyone could give me a shove in the right direction. Thanks.