Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion docs/data/data-grid/filtering/CustomRatingOperator.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import Box from '@mui/material/Box';
import Rating from '@mui/material/Rating';
import { DataGrid } from '@mui/x-data-grid';
import { DataGrid, GridToolbarFilterButton } from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

function RatingInputValue(props) {
Expand Down Expand Up @@ -88,6 +88,7 @@ const ratingOnlyOperators = [
},
InputComponent: RatingInputValue,
InputComponentProps: { type: 'number' },
getValueAsString: (value) => `${value} Stars`,
},
];

Expand Down Expand Up @@ -118,6 +119,9 @@ export default function CustomRatingOperator() {
<DataGrid
{...data}
columns={columns}
components={{
Toolbar: GridToolbarFilterButton,
}}
initialState={{
...data.initialState,
filter: {
Expand Down
5 changes: 5 additions & 0 deletions docs/data/data-grid/filtering/CustomRatingOperator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
DataGrid,
GridFilterItem,
GridFilterOperator,
GridToolbarFilterButton,
} from '@mui/x-data-grid';
import { useDemoData } from '@mui/x-data-grid-generator';

Expand Down Expand Up @@ -62,6 +63,7 @@ const ratingOnlyOperators: GridFilterOperator[] = [
},
InputComponent: RatingInputValue,
InputComponentProps: { type: 'number' },
getValueAsString: (value: number) => `${value} Stars`,
},
];

Expand Down Expand Up @@ -92,6 +94,9 @@ export default function CustomRatingOperator() {
<DataGrid
{...data}
columns={columns}
components={{
Toolbar: GridToolbarFilterButton,
}}
initialState={{
...data.initialState,
filter: {
Expand Down
4 changes: 4 additions & 0 deletions docs/data/data-grid/filtering/filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ The [`valueFormatter`](/x/react-data-grid/column-definition/#value-formatter) is
If the column has a [`valueGetter`](/x/react-data-grid/column-definition/#value-getter), then `params.value` will be the resolved value.
:::

:::info
The filter button displays a tooltip on hover if there are active filters. Pass [`getValueAsString`](/x/api/data-grid/grid-filter-operator/) in the filter operator to customize or convert the value to a more human-readable form.
:::

In the demo below, you can see how to create a completely new operator for the Rating column.

{{"demo": "CustomRatingOperator.js", "bg": "inline", "defaultCodeOpen": false}}
Expand Down
4 changes: 2 additions & 2 deletions docs/data/date-pickers/localization/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
"languageTag": "hu-HU",
"importName": "huHU",
"localeName": "Hungarian",
"missingKeysCount": 0,
"totalKeysCount": 34,
"missingKeysCount": 1,
"totalKeysCount": 35,
"githubLink": "https://github.com/mui/mui-x/blob/next/packages/x-date-pickers/src/locales/huHU.ts/"
},
{
Expand Down
1 change: 1 addition & 0 deletions docs/pages/x/api/data-grid/grid-filter-operator.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { GridFilterOperator } from '@mui/x-data-grid';
| Name | Type | Default | Description |
| :---------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| <span class="prop-name">getApplyFilterFn</span> | <span class="prop-type">(filterItem: GridFilterItem, column: GridColDef&lt;R, V, F&gt;) =&gt; null \| ((params: GridCellParams&lt;R, V, F&gt;) =&gt; boolean)</span> | | The callback that generates a filtering function for a given filter item and column.<br />This function can return `null` to skip filtering for this item and column. |
| <span class="prop-name optional">getValueAsString<sup><abbr title="optional">?</abbr></sup></span> | <span class="prop-type">(value: GridFilterItem['value']) =&gt; string</span> | | Converts the value of a filter item to a human-readable form. |
| <span class="prop-name optional">InputComponent<sup><abbr title="optional">?</abbr></sup></span> | <span class="prop-type">React.JSXElementConstructor&lt;any&gt;</span> | | The input component to render in the filter panel for this filter operator. |
| <span class="prop-name optional">InputComponentProps<sup><abbr title="optional">?</abbr></sup></span> | <span class="prop-type">Record&lt;string, any&gt;</span> | | The props to pass to the input component in the filter panel for this filter operator. |
| <span class="prop-name optional">label<sup><abbr title="optional">?</abbr></sup></span> | <span class="prop-type">string</span> | | The label of the filter operator. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ const GridToolbarFilterButton = React.forwardRef<HTMLButtonElement, GridToolbarF
.getLocaleText(`filterOperator${capitalize(item.operator!)}` as GridTranslationKeys)!
.toString();

const getFilterItemValue = (item: GridFilterItem): string => {
const { getValueAsString } = lookup[item.field!].filterOperators!.find(
(operator) => operator.value === item.operator,
)!;

return getValueAsString ? getValueAsString(item.value) : item.value;
};

return (
<div>
{apiRef.current.getLocaleText('toolbarFiltersTooltipActive')(activeFilters.length)}
Expand All @@ -86,7 +94,7 @@ const GridToolbarFilterButton = React.forwardRef<HTMLButtonElement, GridToolbarF
<li key={index}>
{`${lookup[item.field!].headerName || item.field}
${getOperatorLabel(item)}
${item.value ?? ''}`}
${item.value ? getFilterItemValue(item) : ''}`}
</li>
)),
}))}
Expand Down
6 changes: 6 additions & 0 deletions packages/grid/x-data-grid/src/models/gridFilterOperator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ export interface GridFilterOperator<R extends GridValidRowModel = any, V = any,
* The props to pass to the input component in the filter panel for this filter operator.
*/
InputComponentProps?: Record<string, any>;
/**
* Converts the value of a filter item to a human-readable form.
* @param {GridFilterItem['value']} value The filter item value.
* @returns {string} The value formatted to be displayed in the UI of filter button tooltip.
*/
getValueAsString?: (value: GridFilterItem['value']) => string;
/**
* If `false`, filter operator doesn't require user-entered value to work.
* Usually should be set to `false` for filter operators that don't have `InputComponent` (for example `isEmpty`)
Expand Down
63 changes: 63 additions & 0 deletions packages/grid/x-data-grid/src/tests/filtering.DataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { expect } from 'chai';
import {
DataGrid,
DataGridProps,
GridToolbarFilterButton,
GridColDef,
GridFilterItem,
GridPreferencePanelsValue,
Expand Down Expand Up @@ -1105,6 +1106,68 @@ describe('<DataGrid /> - Filter', () => {
});
});

describe('custom `filterOperators`', () => {
it('should allow to cutomize filter tooltip using `filterOperator.getValueAsString`', () => {
render(
<div style={{ width: '100%', height: '400px' }}>
<DataGrid
filterModel={{
items: [{ field: 'name', operator: 'contains', value: 'John' }],
}}
rows={[
{
id: 0,
name: 'John Doe',
},
{
id: 1,
name: 'Mike Smith',
},
]}
columns={[
{
field: 'name',
type: 'string',
filterOperators: [
{
label: 'Contains',
value: 'contains',
getApplyFilterFn: (filterItem) => {
return (params) => {
if (
!filterItem.field ||
!filterItem.value ||
!filterItem.operator ||
!params.value
) {
return null;
}
return params.value.includes(filterItem.value);
};
},
getValueAsString: (value) => `"${value}" text string`,
},
],
},
]}
components={{ Toolbar: GridToolbarFilterButton }}
/>
</div>,
);

const filterButton = document.querySelector('button[aria-label="Show filters"]');
expect(screen.queryByRole('tooltip')).to.equal(null);

fireEvent.mouseOver(filterButton);
clock.tick(1000); // tooltip display delay

const tooltip = screen.getByRole('tooltip');

expect(tooltip).toBeVisible();
expect(tooltip.textContent).to.contain('"John" text string');
});
});

it('should translate operators dynamically in toolbar without crashing ', () => {
expect(() => {
return (
Expand Down
1 change: 1 addition & 0 deletions packages/x-date-pickers/src/locales/huHU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const huHUPickers: Partial<PickersLocaleText<any>> = {
fieldYearPlaceholder: (params) => 'É'.repeat(params.digitAmount),
fieldMonthPlaceholder: (params) => (params.contentType === 'letter' ? 'HHHH' : 'HH'),
fieldDayPlaceholder: () => 'NN',
// fieldWeekDayPlaceholder: params => params.contentType === 'letter' ? 'EEEE' : 'EE',
fieldHoursPlaceholder: () => 'óó',
fieldMinutesPlaceholder: () => 'pp',
fieldSecondsPlaceholder: () => 'mm',
Expand Down