Heavy filtering with jQuery using data attributes

I have a page of dynamic results from a MySQL table, I’m currently using jQuery to filter them based on a data-town attribute which all ‘blocks’ have been assigned.

I want to filter based on a few other attributes too, but i need the filters to play nice with each other and if one filter has been applied already then the next filter should take that into account and only display results from the already filtered results - not all of the results.

As mentioned above, location is being filtered by a drop down list on the data-town attribute - here is the code;

<select id="town-select" class="soflow">
        <option value="all">Select your location...</option>
        <?php foreach(get_alllocations() as $locationlist): ?>
          <option value="<?php echo htmlentities($locationlist['city'], ENT_QUOTES, 'UTF-8'); ?>"><?php echo htmlentities($locationlist['city'], ENT_QUOTES, 'UTF-8'); ?></option>
        <?php endforeach; ?> 
      </select>

    <script type="text/javascript">
      $("#town-select").change(function(){
        if (this.value === 'all') {
          $("div[data-town]").show();
        } else {
          $("div[data-town]").hide();
          $("div[data-town=" + this.value +"]").show();
        }
      });
    </script>

I want to add the following to that;

  • a couple of range sliders (min and max) / or drop downs for filtering results between two age ranges using data-age attribute - if age is cught by the range it is shown

  • a couple of range sliders (min and max) or drop downs for filtering results between two price ranges using data-price - if the price is caught in the range then it is shown

I’m really struggling trying to combine additional jquery with my existing code - any help would be greatly appreciated.

2 Likes

Check the following simple example about to apply two filters() methods with a callback functions inside and try to set this in yourcode:

<select id="town-select" class="soflow">
    <option value=""> Select</option>
    <option value="A" data-age="25">25</option>
    <option value="A" data-age="40">40</option>
    <option value="B" data-age="35">35</option>
    <option value="A" data-age="55">55</option>
    <option value="B" data-age="65">65</option>
    <option value="A"  data-age="45">45</option>
    <option value="B" data-age="15">15</option>
</select>

<script>
    $('option').hide();
    $('option').filter(function(){
         return $(this).val()==='A';
         }).filter(function(){
            return $(this).data('age')>='40';
    }).show();     
  </script>

I’m not sure I understand…

I have several seperate form fields that need to filter a page of div elements but need to take each other in to account. I don’t want to filter anything with one single field.

In this case you can use another selector eg:

$('#town-select > option').hide();
$('#town-select > option').filter(function(){
 return $(this).val()==='A';
}).filter(function(){
  return $(this).data('age')>='40';
}).show();

As first selector you can define via id or class the form that you want to filter.

Hello there.
I recently had similar trouble combining filters too. I suggest that you render your list depending on an array of objects. This way you can use Array.filter to filter the items, and Array.reduce within the filter function to find out if the combination of filters applies to the item.

I wrote more in depth regarding that problem on my blog. To share my approach on how to deal with multiple filters. Although, I don’t use any jquery and explain more about the functions that deal with the data directly.

I hope this helps.

https://happy-css.com/articles/how-to-group-together-filter-inputs-to-obtain-and-combine-their-values/

I only use text filters and dropdowns in the example. However, you can extend the example with sliders. https://refreshless.com/nouislider/ is a great library to use for range sliders. They have a beautiful API which is easy to integrate with existing projects. Please let me know if you have any other questions on that topic, I’m happy to help!

Best,
Martin

1 Like

Thanks for this - I really like the approach you’ve taken.

At present, I have my filters working but it remains to be seen whether it will fall over the more filter options I add.

You say in your post that the data should be in JSON format - how do I go about pulling data from the database into a JSON file? For the filters to be of any use in my project the data needs to be dynamic and drawn from the DB.

Hello! Great to see that you enjoyed the approach I have taken :slight_smile:
I always try to avoid direct DOM manipulation and render data from an array of objects. This is possible in jquery too. For now, you are good to go, if you overwrite the HTML every time the filter changes.

It is tough to combine back-end code with front-end sometimes. Especially when you try to make them interact with each other. You only have to care about one-way manipulation right now - bringing the data from back-end to front-end and then filter that using javascript with jQuery.

JSON is a data format. Not necessarily a file format (it is too, but we just need the data here - no file)
To get data from one format into another should be no problem. You use PHP. Then you can use json_encode(). I found a stackoverflow question here: https://stackoverflow.com/questions/383631/json-encode-mysql-results and you can read about json_encode here: http://php.net/manual/en/function.json-encode.php

If you don’t have a REST API to serve your data (which is more comfortable in terms of handing over data) you can assign the data with an inline script and php combined (which is a little ugly, but the easiest and most straight forward solution right now)

<?php
$sth = mysqli_query("SELECT ...");
$rows = array();
while($r = mysqli_fetch_assoc($sth)) {
    $rows[] = $r;
}
?>
<script>
var items = <?=json_encode($rows)?>
// render items using jquery.
</script>

There are many different ways to go about implementing this. If you care about accessibility and fallbacks, you would first render the items using php, and make the form for the filters - when submitted - reload the page with GET params to filter depending on the options given. And use javascript - if enabled - to offer real-time filtering of items.

Depending on your requirements, it is easier to use javascript only to render and filter. It is way more complex to get everything right in the first run (especially if you have to run both front-end and back-end code!), so lets focus on javascript first.

By the way: I created a range slider example to filter between two values: http://plnkr.co/edit/uxiqDmREzrKJfpzTRlIx?p=preview

Feel free to get back to me with any questions. Getting all the technologies together is hard, but you have to keep on trying :slight_smile:

1 Like

Thanks a lot for this. I will take a look at it this evening when I have the time to get to it… I’ll feedback what I find out.

Alright Ben.

I prepared another post explaining how to do that with plain javascript and using a range slider.
Please let me know if this helps to solve the problem. You should also be able to integrate this with your existing code base.
https://happy-css.com/articles/using-nouislider-as-range-slider-to-filter-between-two-numbers/

1 Like

Thanks @MartinMuzatko.

I took a break from working on the app for awhile. Great article, I’m sure it will be of help.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.