Demo - FlexGridFilter

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.grapecity.com/wijmo/5.latest/styles/wijmo.min.css">
<script src="https://cdn.grapecity.com/wijmo/5.latest/controls/wijmo.min.js"></script>
<script src="https://cdn.grapecity.com/wijmo/5.latest/controls/wijmo.grid.min.js"></script>
<script src="https://cdn.grapecity.com/wijmo/5.latest/controls/wijmo.input.min.js"></script>
<script src="https://cdn.grapecity.com/wijmo/5.latest/controls/wijmo.grid.filter.min.js"></script>
<div class="container">

  <h1>
    FlexGridFilter</h1>
  <p>
    The <b>wijmo.grid.filter</b> module provides a <b>FlexGridFilter</b>
    class that adds an Excel-style filtering UI to each column.</p>
  <p>
    The <b>FlexGridFilter</b> adds filter icons to the column headers.
    Users may click the icons to see a drop-down where they can apply
    filters by value or by condition:</p>
  <div id="theGrid">
  </div>
</div>

CSS

.wj-flexgrid {
  max-height: 250px;
  margin:10px 0;
}
body {
  margin-bottom: 20px;
}

JavaScript

onload = function () {

  // generate some random data
  var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(','),
      data = getTreeData();

	// FlexGridFilter client-side filtering
  var theGrid = new wijmo.grid.FlexGrid('#theGrid', {
    itemsSource: data,
    childItemsPath: 'cities'
  });
  var filter = new wijmo.grid.filter.FlexGridFilter(theGrid);
  
  makeFilterHierarchical(filter, true);
}

function makeFilterHierarchical(filter, showChildRowsIfParentPassesFilter){
    filter.filterApplied.addHandler((s, e) => {
      filter.grid.collectionView.filter = null;
    });

    filter.grid.collectionView.collectionChanged.addHandler((s,e)=>{
      updateRowsVisibility(filter);
    });

    filter['_showChildRowsForVisibleParent'] = showChildRowsIfParentPassesFilter? true: false;
  }

 function updateRowsVisibility(filter) {
    var rows = filter.grid.rows;
    for (var i = 0; i < rows.length; i++) {
      var row = rows[i],
        state = row.dataItem,
        rng = row.getCellRange();

      // handle (level 0)  
      if (row.level == 0) {
        updateGroupVisibility(filter.grid, filter, row.getCellRange());
        i = rng.bottomRow;
      }
    }
  }
  
  function updateGroupVisibility(grid, filter, rng) {
    let root = grid.rows[rng.topRow];
    let rootVisible = checkDataItemPassFilter(grid, filter, root.dataItem);
    let childVisible = false;

    let showChildRowsIfParentPassesFilter = filter['_showChildRowsForVisibleParent']? true: false;
    if(rootVisible && showChildRowsIfParentPassesFilter){
      // it does, so show all its items(optional)
      for (let j = rng.topRow + 1; j <= rng.bottomRow; j++) {
        setRowVisibility(grid, j, true, true);
      }
    }
    else if(!rootVisible || !showChildRowsIfParentPassesFilter){
      // update child rows
      // it does not, so check child items
      for (let j = rng.topRow + 1; j <= rng.bottomRow; j++) {
        let childRow = grid.rows[j];
        let tempChildVisible;
       ...