React Data Grid - Custom Filterable Header Cell
[ 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!