Tuesday, May 14, 2024
 Popular · Latest · Hot · Upcoming
181
rated 0 times [  188] [ 7]  / answers: 1 / hits: 5732  / 2 Years ago, mon, august 1, 2022, 12:00:00

Let's say I have a datagrid table like so (from the official MUI documentation):


import * as React from 'react';
import { DataGrid, GridToolbar } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

const VISIBLE_FIELDS = ['name', 'rating', 'country', 'dateCreated', 'isAdmin'];

export default function ControlledFilters() {
const { data } = useDemoData({
dataSet: 'Employee',
visibleFields: VISIBLE_FIELDS,
rowLength: 100,
});

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
{...data}
components={{
Toolbar: GridToolbar,
}}
/>
</div>
);
}

Now let's say I wanted to filter the column 'name' in this table by onClick of a button. That button, when clicked, should give a string, let's say 'Ray'. When this button is clicked, I want to automatically filter the table so that every value in the 'name' column that contains the string 'Ray' only gets displayed.


My Approach so far


I have tried using useState from react and the filterModel prop in DataGrid so that pressing the button filters the table like so:


  ....

const [filt, setFilt] = useState('') // Initialize it with an empty filter
const handleClick = () => {
setFilt('Ray');
};

return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
{...data}
components={{
Toolbar: GridToolbar,
}}
filterModel={{
items: [{ columnField: 'name', operatorValue: 'contains', value: filt },
]
}}
/>

<Button onClick={handleClick}>Change Filter</Button>
</div>
);
}

This works but the problem with this approach is that it locks every other filter and the filter is basically stuck on the 'name' column and the user can now only use the button to filter the column. It doesn't even let me remove the filter.


I have also tried the onFilterModelChange prop but it didn't work; I am honestly confused on how to use it for this specific case. Any help would be appreciated.


More From » reactjs

 Answers
1

You were close. I believe that you would need to form the entire items array instead of only a part of the filter object.


i.e. setFilt([{ columnField: 'name', operatorValue: 'contains', value: "Ray"}]) instead of setFilt("Ray") along with { columnField: 'name', operatorValue: 'contains', value: filt}


You can reset the filters by setting items: [] in the filterModel.


CodeSandbox Example with a single filter criterion.


(I had to install @mui/material v5.9.2 instead of v5.9.3 to get it to work if you have any compile issues on codesandbox)


const [filt, setFilt] = useState([])

<DataGrid
{...data}
filterModel={{
items: filt
}}
/>
<Button
onClick={() =>
setFilt([
{
columnField: "name",
operatorValue: "startsWith",
value: "A"
}
])
}
>
Name Starts With A
</Button>
<Button
onClick={() => setFilt([])}
>
Reset Filters
</Button>

Bonus: Multi-filtering with buttons


CodeSandbox Example of a multi-filter grid with buttons.


Multi-filtering is only possible with the Pro version of MUI. Without the Pro version, any additional filters added past the first one are ignored (as you discovered).


This is what I came up with using @mui/x-data-grid-pro and 3 different buttons that each apply a unique filter:


const [filt, setFilt] = useState([])

<DataGridPro
{...data}
filterModel={{
items: filt,
GridLinkOperator: GridLinkOperator.And
}}
/>
<Button
onClick={() =>
setFilt([
...filt,
{
id: 1,
columnField: "rating",
operatorValue: ">",
value: 3
}
])
}
>
Rating Greater Than 3
</Button>
<Button
onClick={() =>
setFilt([
...filt,
{
id: 2,
columnField: "name",
operatorValue: "startsWith",
value: "A"
}
])
}
>
Name Starts With A
</Button>
<Button
onClick={() => setFilt([])}
>
Reset Filters
</Button>

A caveat to be aware of --- you will need to add an id to each filter object in the items array when using multi-filtering.


e.g.


[
{ id: 1, columnField: 'rating', operatorValue: '>', value: 3 },
{ id: 2, columnField: 'name', operatorValue: 'startsWith', value: "A" }
]

remember this code not work in real time anymore


##Update: Now a day you must use onFilterModelChange ##


const [filt, setFilt] = useState({
items: [{
}]

})

<DataGrid
{...data}
filterModel={filt}
onFilterModelChange={(newFilterModel) =>
setFilt(newFilterModel)
}
/>
<Button
onClick={() =>
setFilt([
{
columnField: "name",
operatorValue: "startsWith",
value: "A"
}
])
}
>
Name Starts With A
</Button>
<Button
onClick={() => setFilt([])}
>
Reset Filters
</Button>

with onFilterModalChange props you can update your table filter


[#47] Tuesday, July 5, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
declanm

Total Points: 614
Total Questions: 105
Total Answers: 97

Location: Dominica
Member since Sat, Nov 5, 2022
2 Years ago
declanm questions
Fri, Dec 18, 20, 00:00, 3 Years ago
Fri, Aug 7, 20, 00:00, 4 Years ago
Thu, Apr 2, 20, 00:00, 4 Years ago
;