Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Column Header Filter #1140

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,5 @@ package-lock.json

# visualizer
stats.html

.yarn
2 changes: 1 addition & 1 deletion .storybook/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ addons.setConfig({
theme: create({
base: 'light',
brandTitle: 'React Data Table Component',
brandUrl: 'https://github.com/jbetancur/react-data-table-component',
brandUrl: 'https://github.com/AnotherCodeArtist/react-data-table-component',
gridCellSize: 12,
}),
});
7 changes: 7 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Chrome",
"port": 9222,
"request": "attach",
"type": "pwa-chrome",
"webRoot": "${workspaceFolder}"
},
{
"name": "Debug Tests",
"type": "node",
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"editor.defaultFormatter": "rvest.vs-code-prettier-eslint"
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
Expand Down
Binary file modified .yarn/install-state.gz
Binary file not shown.
16 changes: 5 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
[![Netlify Status](https://api.netlify.com/api/v1/badges/26e0d16d-a986-46b1-9097-1a76c10d7cad/deploy-status)](https://app.netlify.com/sites/react-data-table-component/deploys) [![npm version](https://badge.fury.io/js/react-data-table-component.svg)](https://badge.fury.io/js/react-data-table-component) [![codecov](https://codecov.io/gh/jbetancur/react-data-table-component/branch/master/graph/badge.svg)](https://codecov.io/gh/jbetancur/react-data-table-component) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

# React Data Table Component

[![GitHub release](https://img.shields.io/github/release/jbetancur/react-data-table-component.svg)](https://GitHub.com/jbetancur/react-data-table-component/releases/)
**Note**: This is a clone of [https://github.com/jbetancur/react-data-table-component](https://github.com/jbetancur/react-data-table-component) with one additional feature: [Column Filtering](https://anothercodeartist.github.io/react-data-table-component/?path=/story/general--kitchen-sink). It seems that there's no development going on any longer there.

Creating yet another React table library came out of necessity while developing a web application for a growing startup. I discovered that while there are some great table libraries out there, some required heavy customization, were missing out of the box features such as built in sorting and pagination, or required understanding the atomic structure of html tables.

If you want to achieve balance with the force and want a simple but flexible table library give React Data Table Component a chance. If you require an Excel clone, then this is not the React table library you are looking for 👋

# Key Features

- **Filterable columns**
- Declarative configuration
- Built-in and configurable:
- Sorting
Expand All @@ -20,13 +19,13 @@ If you want to achieve balance with the force and want a simple but flexible tab
- Accessibility
- Responsive (via x-scroll/flex)

# Documentation Website
In this version filterability was further improved by adding an additional column property called `filterValues`, which is a list of values that filtering is restricted to. This is helpful in cases where a column has only a small set of different values.

[![Netlify Status](https://api.netlify.com/api/v1/badges/26e0d16d-a986-46b1-9097-1a76c10d7cad/deploy-status)](https://app.netlify.com/sites/react-data-table-component/deploys)
# Documentation Website

The documentation contains information about installation, usage and contributions.

https://react-data-table-component.netlify.app
https://anothercodeartist.github.io/react-data-table-component

# Supporting React Data Table Component

Expand All @@ -37,8 +36,3 @@ If you would like to support the project financially, visit
<img src="https://opencollective.com/react-data-table-component/contribute/[email protected]?color=blue" width="250px" />
</a>

# Contributors

<a href="https://github.com/jbetancur/react-data-table-component/graphs/contributors">
<img src="https://opencollective.com/react-data-table-component/contributors.svg?width=890" />
</a>
7 changes: 7 additions & 0 deletions eslintrc-js.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ module.exports = {
'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies
'react/jsx-props-no-spreading': 0,
'react/display-name': 0,
'@typescript-eslint/no-unused-vars': [
'error',
{
ignoreRestSiblings: true,
argsIgnorePattern: '_',
},
],
},
env: {
'jest/globals': true,
Expand Down
11 changes: 11 additions & 0 deletions eslintrc-ts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
rules: {
'@typescript-eslint/no-unused-vars': [
'error',
{
ignoreRestSiblings: true,
argsIgnorePattern: '_',
},
],
},
};
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "react-data-table-component",
"name": "react-data-table-component-with-filter",
"version": "7.6.2",
"description": "A simple to use declarative react based data table",
"main": "dist/index.cjs.js",
Expand All @@ -18,8 +18,8 @@
"react-data-table",
"react-data-table-component"
],
"repository": "https://github.com/jbetancur/react-data-table-component",
"author": "jbetancur",
"repository": "https://github.com/anothercodeartist/react-data-table-component",
"author": "AnotherCodeArtist",
"license": "Apache-2.0",
"prepublish": "tsc",
"scripts": {
Expand Down
50 changes: 43 additions & 7 deletions src/DataTable/DataTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { CellBase } from './Cell';
import NoData from './NoDataWrapper';
import NativePagination from './Pagination';
import useDidUpdateEffect from '../hooks/useDidUpdateEffect';
import { prop, getNumberOfPages, sort, isEmpty, isRowSelected, recalculatePage } from './util';
import { prop, getNumberOfPages, sort, isEmpty, isRowSelected, recalculatePage, getProperty } from './util';
import { defaultProps } from './defaultProps';
import { createStyles } from './styles';
import {
Expand All @@ -30,6 +30,7 @@ import {
TableProps,
TableState,
SortOrder,
FilterAction,
} from './types';
import useColumns from '../hooks/useColumns';

Expand Down Expand Up @@ -97,8 +98,10 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {
onRowMouseLeave = defaultProps.onRowMouseLeave,
sortIcon = defaultProps.sortIcon,
onSort = defaultProps.onSort,
onFilter = defaultProps.onFilter,
sortFunction = defaultProps.sortFunction,
sortServer = defaultProps.sortServer,
filterServer = defaultProps.filterServer,
expandableRowsComponent = defaultProps.expandableRowsComponent,
expandableRowsComponentProps = defaultProps.expandableRowsComponentProps,
expandableRowDisabled = defaultProps.expandableRowDisabled,
Expand Down Expand Up @@ -139,6 +142,8 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {
selectedCount,
selectedColumn,
sortDirection,
filters,
filterActive,
toggleOnSelectedRowsChange,
},
dispatch,
Expand All @@ -151,6 +156,9 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {
sortDirection: defaultSortDirection,
currentPage: paginationDefaultPage,
rowsPerPage: paginationPerPage,
filteredData: data,
filterActive: false,
filters: {},
selectedRowsFlag: false,
contextMessage: defaultProps.contextMessage,
});
Expand All @@ -162,22 +170,41 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {

const currentTheme = React.useMemo(() => createStyles(customStyles, theme), [customStyles, theme]);
const wrapperProps = React.useMemo(() => ({ ...(direction !== 'auto' && { dir: direction }) }), [direction]);
const escapeRegex = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
const currentData = React.useMemo(() => {
if (filterActive && !filterServer) {
return data.filter((row, idx) =>
Object.entries(filters).reduce(
(
acc: boolean,
[_, { column, value }], // eslint-disable-line @typescript-eslint/no-unused-vars
) =>
new RegExp(`.*${escapeRegex(value)}.*`, 'i').test(getProperty(row, column.selector, null, idx)?.toString() ?? '')
? acc
: false,
true,
),
);
} else {
return data;
}
}, [filters, filterServer, data, filterActive]);

const sortedData = React.useMemo(() => {
// server-side sorting bypasses internal sorting
if (sortServer) {
return data;
return currentData;
}

if (selectedColumn?.sortFunction && typeof selectedColumn.sortFunction === 'function') {
const sortFn = selectedColumn.sortFunction;
const customSortFunction = sortDirection === SortOrder.ASC ? sortFn : (a: T, b: T) => sortFn(a, b) * -1;

return [...data].sort(customSortFunction);
return [...currentData].sort(customSortFunction);
}

return sort(data, selectedColumn?.selector, sortDirection, sortFunction);
}, [sortServer, selectedColumn, sortDirection, data, sortFunction]);
return sort(currentData, selectedColumn?.selector, sortDirection, sortFunction);
}, [sortServer, selectedColumn, sortDirection, currentData, sortFunction]);

const tableRows = React.useMemo(() => {
if (pagination && !paginationServer) {
Expand All @@ -187,14 +214,17 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {

return sortedData.slice(firstIndex, lastIndex);
}

return sortedData;
}, [currentPage, pagination, paginationServer, rowsPerPage, sortedData]);

const handleSort = React.useCallback((action: SortAction<T>) => {
dispatch(action);
}, []);

const handleFilter = React.useCallback((action: FilterAction<T>) => {
dispatch(action);
}, []);

const handleSelectAllRows = React.useCallback((action: AllRowsAction<T>) => {
dispatch(action);
}, []);
Expand Down Expand Up @@ -261,7 +291,7 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {
return true;
}

return sortedData.length > 0 && !progressPending;
return filterActive || (sortedData.length > 0 && !progressPending);
};

const showHeader = () => {
Expand Down Expand Up @@ -302,6 +332,10 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {
onChangePage(currentPage, paginationTotalRows || sortedData.length);
}, [currentPage]);

useDidUpdateEffect(() => {
onFilter(filters);
}, [filters]);

useDidUpdateEffect(() => {
onChangeRowsPerPage(rowsPerPage, currentPage);
}, [rowsPerPage]);
Expand Down Expand Up @@ -414,7 +448,9 @@ function DataTable<T>(props: TableProps<T>): JSX.Element {
sortDirection={sortDirection}
sortIcon={sortIcon}
sortServer={sortServer}
filterServer={filterServer}
onSort={handleSort}
onFilter={handleFilter}
onDragStart={handleDragStart}
onDragOver={handleDragOver}
onDragEnd={handleDragEnd}
Expand Down
Loading