From 1484fb6ce3accaeaaf2c7b4c1e8d1b8af4b71a00 Mon Sep 17 00:00:00 2001 From: cococov Date: Mon, 11 Dec 2023 12:41:42 -0300 Subject: [PATCH] feat: add the option to change the filter operator --- __tests__/demo/demo-components/index.js | 128 +++++++++++++++++++++++- __tests__/demo/demo.js | 3 + src/material-table.js | 7 +- src/utils/data-manager.js | 7 ++ 4 files changed, 141 insertions(+), 4 deletions(-) diff --git a/__tests__/demo/demo-components/index.js b/__tests__/demo/demo-components/index.js index 82f45cb9..a0e5ced3 100644 --- a/__tests__/demo/demo-components/index.js +++ b/__tests__/demo/demo-components/index.js @@ -1,6 +1,13 @@ import React, { useState, useEffect, useRef } from 'react'; -import { Box, Input, InputAdornment } from '@mui/material'; +import { + Box, + Input, + InputAdornment, + TextField, + Select, + MenuItem +} from '@mui/material'; import SearchIcon from '@mui/icons-material/Search'; // root of this project @@ -1467,3 +1474,122 @@ export function LocalizationWithCustomComponents() { /> ); } + +function CustomFilterWithOperatorSelection({ columnDef, onFilterChanged }) { + const [operator, setOperator] = React.useState('='); + const [value, setValue] = React.useState(undefined); + const operatorRef = React.useRef(operator); + const valueRef = React.useRef(value); + + React.useEffect(() => { + if (operatorRef.current !== operator || valueRef.current !== value) { + onFilterChanged(columnDef.tableData.id, value, operator); + operatorRef.current = operator; + valueRef.current = value; + } + }, [operator, value]); + + return ( + + + setValue(e.target.value)} + /> + + ); +} + +const columns_with_custom_filter = [ + { title: 'Name', field: 'name', filtering: true }, + { + title: 'Some Number', + field: 'some_number', + filtering: true, + filterComponent: ({ columnDef, onFilterChanged }) => ( + + ) + } +]; + +const data_with_custom_filter = [ + { name: 'Juan', some_number: 1 }, + { name: 'John', some_number: 4 }, + { name: 'Pedro', some_number: 8 }, + { name: 'Mary', some_number: 12 }, + { name: 'Oliver', some_number: 2 }, + { name: 'Ignacio', some_number: 4 } +]; + +export function FilterWithOperatorSelection() { + return ( + + new Promise((resolve, _reject) => { + if (query.filters.length > 0) { + query.filters.forEach((filter) => { + if ( + filter.value !== undefined && + filter.value !== null && + filter.value !== '' + ) { + switch (filter.operator) { + case '=': + resolve({ + data: data_with_custom_filter.filter( + (row) => row[filter.column.field] == filter.value + ), + page: 1, + totalCount: data_with_custom_filter.length + }); + break; + case '>': + resolve({ + data: data_with_custom_filter.filter( + (row) => row[filter.column.field] > filter.value + ), + page: 1, + totalCount: data_with_custom_filter.length + }); + break; + case '<': + resolve({ + data: data_with_custom_filter.filter( + (row) => row[filter.column.field] < filter.value + ), + page: 1, + totalCount: data_with_custom_filter.length + }); + break; + } + } + }); + } + resolve({ + data: data_with_custom_filter, + page: 1, + totalCount: data_with_custom_filter.length + }); + }) + } + columns={columns_with_custom_filter} + options={{ + search: false, + filtering: true + }} + /> + ); +} diff --git a/__tests__/demo/demo.js b/__tests__/demo/demo.js index f281eda8..8f8eb8d4 100644 --- a/__tests__/demo/demo.js +++ b/__tests__/demo/demo.js @@ -48,6 +48,7 @@ import { TableWithSummary, TableWithNumberOfPagesAround, FixedColumnWithEdit, + FilterWithOperatorSelection, TableMultiSorting, LocalizationWithCustomComponents } from './demo-components'; @@ -154,6 +155,8 @@ function Demo() {

Localization with Custom Components

+

Filter with operator selection

+

Remote Data Related

  1. diff --git a/src/material-table.js b/src/material-table.js index 784bcb9b..5a56cd7a 100644 --- a/src/material-table.js +++ b/src/material-table.js @@ -788,8 +788,9 @@ export default class MaterialTable extends React.Component { } }, this.props.options.debounceInterval); - onFilterChange = (columnId, value) => { + onFilterChange = (columnId, value, operator = '=') => { this.dataManager.changeFilterValue(columnId, value); + this.dataManager.changeFilterOperator(columnId, operator); this.setState({}, this.onFilterChangeDebounce); }; @@ -801,7 +802,7 @@ export default class MaterialTable extends React.Component { .filter((a) => a.tableData.filterValue) .map((a) => ({ column: a, - operator: '=', + operator: a.tableData.filterOperator, value: a.tableData.filterValue })); @@ -815,7 +816,7 @@ export default class MaterialTable extends React.Component { .filter((a) => a.tableData.filterValue) .map((a) => ({ column: a, - operator: '=', + operator: a.tableData.filterOperator, value: a.tableData.filterValue })); this.props.onFilterChange(appliedFilters); diff --git a/src/utils/data-manager.js b/src/utils/data-manager.js index 872c1708..63c0a2ca 100644 --- a/src/utils/data-manager.js +++ b/src/utils/data-manager.js @@ -273,6 +273,13 @@ export default class DataManager { this.filtered = false; } + changeFilterOperator(columnId, operator) { + const column = this.columns.find((c) => c.tableData.id === columnId); + + column.tableData.filterOperator = operator; + this.filtered = false; + } + changeRowSelected(checked, path) { const rowData = this.findDataByPath(this.sortedData, path); rowData.tableData.checked = checked;