ZingGrid - Smart Filtering Defaults

Being a relatively new member of the Zing team, I haven’t had a chance yet to see most of the hard work that was put in before I got here. As the new Zing DevRel I thought I’d share my learnings as I unearth the latest of what ZingGrid has to offer.

This past year has brought more than just stability and bug patches—so many great features have been added to ZingGrid to expand its capabilities and deepen your tool belt as an engineer. This post will be the first part of a three part series where I’ll be going over all of the major improvements that have been added from v.1.5.0 up to now (v.1.7.1-0)

This post in particular will be focused on everything filtering. If at any point you'd like to skip straight to the docs, here is a link to the filtering specific docs.

Old Defaults

Before I dive into what's new, it's helpful to see what we had before to give context and motivation for the changes.

Now referred to as inline filtering, these filters insert input fields between the column headers and data which allow users to show only the rows that have a substring match with the given input. These are the old default filters for ZingGrid pre-v.1.7.0

💡
NOTE: You can still access this old style of filtering, you just need to specify filter="inline" on either the <zing-grid> or <zg-column> elements

While useful, this demo immediately brings up some questions in my mind:

  • How do I filter for values less than a specific number?
  • How do I filter out users that do not have an email?
  • How do I filter for users whose name start with certain letters?
  • How can I filter out specific rows without needing a specific condition?

Custom Filter Conditions

Luckily v.1.7.0 of ZingGrid brings logical operators amongst other filter conditions which solve those exact issues.

Adding filter (as a Boolean attribute with no value) to either the <zing-grid> or <zg-column> elements will cause filter buttons to appear next to each column header. These buttons trigger smart pop-up menus that give a set of options determined by the type of the column. If the defaults aren't fitting your needs though, there are dozens more conditions available which you can check out in the filter docs here.

If you want to be able to hide any specific rows for one reason or another, you can also apply the filter-menu-areas="selectbox" attribute to any zg-column. This will display a list of checkboxes next to each row's entries in the filter menu allowing you to selectively filter out any rows you like.

Now back to the questions from earlier:

How do I filter for values less than a specific number?
0:00
/0:08
How do I filter out users that do not have an email?
0:00
/0:07

Filtering empty rows from an email column in a ZingGrid

How do I filter for users whose name start with certain letters?
0:00
/0:10

Filtering for first names that begin with the letter "M" in a ZingGrid

How can I filter out specific rows without needing a specific condition?
0:00
/0:08

Filtering out three emails manually with the filter-menu-areas="checkbox" attribute

Below is the demo so you can poke around and play for yourself.

Custom Filtering (Inline)

While the new default filter menu is powerful and the recommended way to go, the inline filter is still available so we've given some functional hooks into it if you find yourself limited.

As I mentioned above, by default the inline filter just allows you to do a substring match on that column to limit the number of rows. While this is handy, it would be nice to be able to hook into the filter function and run custom code to do things like enforce filter formatting, limit the filter character set, do some simple spell checking, or any number of complex interactions.

In the demo below we’ll be looking at how we can enforce custom filter formatting (proper capitalization of first and last names) using the filterer attribute to specify a custom function.

How to Use

You must first specify that your grid should have inline filters so than you can modify them. You do this by adding filter="inline" to your <zing-grid> or <zg-column>

<zing-grid filter="inline"></zing-grid>

Then, on any <zg-column> where you want to customize the filter, add a filterer attribute that specifies the name of the filter object you would like to use. Here, I named my object customFilter but that’s just a name I picked arbitrarily. We need to make sure this variable is exposed to the window object so ZingGrid can access it.

<zing-grid filter="inline">
  <zg-column filterer="customFilter"></zg-column>
</zing-grid>

<script type="module">
  window.customFilter = {
    /* TODO */
  };
</script>

Now we just need to fill in the function. We have a few methods with which we can override some of the filter’s functionality.

  • init : (Optional) will override the default initialization of the <zg-filter> and replace it with the returned <zg-filter> (A handle for this filter is passed in as a parameter, it must be passed back).
  • afterInit : (Optional) will execute this code after the <zg-filter> has been initialized. Passes in a handle for the <zg-filter> as a parameter so you can attach event listeners to it or whatever you would like.
  • value : (Optional) is used to determine the value of the <zg-filter>. Useful if you created your own <input> elements in init so that ZingGrid is able to interact with it. Must return a value.
  • setValue : (Optional) similar to value in that if you created a custom <input> in the init function you likely need to provide ZingGrid a way to interact with it via this method. Sets the value of the <zg-filter>
  • triggerEvent : (Optional) determines which event is used to execute the filter. By default this is 'keyup' but can be changed to any valid DOM event that might bubble through <zg-filter>
<zing-grid filter="inline">
  <zg-column filterer="customFilter"></zg-column>
</zing-grid>

<script type="module">
  window.customFilter = {
    init(oDOMFilter) { /* must return oDOMFilter */ },
    afterInit(oDOMFilter) { /* no return */ },
    value(oDOMFilter) { /* must return value */ },
    setValue(sValue, oDOMFilter) { /* no return */ },
    triggerEvent: 'keyup'
  };
</script>

And below is a demo of it all together: