JasonSears.io

Logo

Enterprise Cloud Enthusiast

Senior Solutions Architect / Chicago Technology Lead at Rightpoint

About | GitHub

React Data Grid - Custom Filterable Header Cell

May 17, 2020

[ Web ] [ TypeScript, React, react-data-grid ]

Recently, I was looking into creating a custom column filter for a react-data-grid instance, which simply excluded characters from the input element.

There are custom header filters in react-data-grid-addons. However, after inspecting the markup created by the default header cell filter, shown below, I noticed it didn’t match any of the filters in react-data-grid-addons (NumericFilter, AutoCompleteFilter, MultiSelectFilter, SingleSelectFilter):

<div>
  <div class="form-group"><input type="text" class="form-control input-sm" placeholder="Search" value="">
  </div>
</div>

After doing some digging, I found the codebase-overview page for react-data-grid. It mentions the following:

  • Currently there are three packages:
    • react-data-grid the core package of the grid, contains all the core functionality of the project
    • react-data-grid-addons a set of addons for the base grid, containing things like toolbars, custom editors…
    • react-data-grid-examples a playground for the project, this is where you can check your changes for real.
  • There is also a common folder which contains common code between all packages.

After looking into the common folder, I found the default header cell filter. Based off of this, I created a custom column filter, with a higher-order component to take in an additional array prop to exclude characters from the input element: forbiddenCharacters.

Here is the code for the new filter:

import React, { useState } from 'react';
import { Column } from 'react-data-grid';

interface IFilterableHeaderCell {
  onChange: (filter: { filterTerm: string; column: Column<any> }) => Promise<void>;
  column: Column<any>;
  forbiddenCharacters: string[];
}

const FilterableHeaderCell: React.FC<IFilterableHeaderCell> = props => {
  const { onChange, column, forbiddenCharacters } = props;

  const [filterTerm, setFilterTerm] = useState<string>('');

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    let val = e.target.value || '';

    // remove all forbidden characters
    if (forbiddenCharacters && forbiddenCharacters.length > 0) {
      const forbiddenCharacterList = forbiddenCharacters.join('|');
      const regex = new RegExp(forbiddenCharacterList, 'g');
      val = val.replace(regex, '');
    }

    setFilterTerm(val);
    onChange({ filterTerm: val, column: column });
  };

  const renderInput = () => {
    if (column.filterable === false) {
      return <span />;
    }

    const inputKey = 'header-filter-' + column.key;
    return (
      <input
        key={inputKey}
        type="text"
        className="form-control input-sm"
        placeholder="Search"
        value={filterTerm}
        onChange={handleChange}
      />
    );
  };

  return (
    <div>
      <div className="form-group">{renderInput()}</div>
    </div>
  );
};

const CreateFilterableHeaderCell = (forbiddenCharacters: string[]) => {
  return (props: IFilterableHeaderCell) => (
    <FilterableHeaderCell {...props} forbiddenCharacters={forbiddenCharacters} />
  );
};

export default CreateFilterableHeaderCell;

Here is the full source code for the new filter:
https://github.com/jasonds/react-data-grid-custom-filterable-header-cell

Using the new source code above, here is a codesandbox, with the new filter:
https://codesandbox.io/s/purple-https-jeute


Jason Sears

Share this post!