Skip to content

Commit

Permalink
feat: add the option to change the filter operator (#816)
Browse files Browse the repository at this point in the history
  • Loading branch information
cococov committed Dec 11, 2023
1 parent 75b559b commit 1a5084a
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 4 deletions.
128 changes: 127 additions & 1 deletion __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
Expand Down Expand Up @@ -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 (
<span>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
variant="standard"
value={operator}
onChange={(e) => setOperator(e.target.value)}
>
<MenuItem value={'='}>=</MenuItem>
<MenuItem value={'>'}>&gt;</MenuItem>
<MenuItem value={'<'}>&lt;</MenuItem>
</Select>
<TextField
variant="standard"
onChange={(e) => setValue(e.target.value)}
/>
</span>
);
}

const columns_with_custom_filter = [
{ title: 'Name', field: 'name', filtering: true },
{
title: 'Some Number',
field: 'some_number',
filtering: true,
filterComponent: ({ columnDef, onFilterChanged }) => (
<CustomFilterWithOperatorSelection
columnDef={columnDef}
onFilterChanged={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 (
<MaterialTable
data={(query) =>
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
}}
/>
);
}
3 changes: 3 additions & 0 deletions __tests__/demo/demo.js
Expand Up @@ -48,6 +48,7 @@ import {
TableWithSummary,
TableWithNumberOfPagesAround,
FixedColumnWithEdit,
FilterWithOperatorSelection,
TableMultiSorting,
LocalizationWithCustomComponents
} from './demo-components';
Expand Down Expand Up @@ -154,6 +155,8 @@ function Demo() {
<FixedColumnWithEdit />
<h1>Localization with Custom Components</h1>
<LocalizationWithCustomComponents />
<h1>Filter with operator selection</h1>
<FilterWithOperatorSelection />
<h1>Remote Data Related</h1>
<ol>
<li>
Expand Down
7 changes: 4 additions & 3 deletions src/material-table.js
Expand Up @@ -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);
};

Expand All @@ -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
}));

Expand All @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/utils/data-manager.js
Expand Up @@ -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;
Expand Down

0 comments on commit 1a5084a

Please sign in to comment.