diff --git a/packages/grid/x-data-grid/src/components/cell/GridEditSingleSelectCell.tsx b/packages/grid/x-data-grid/src/components/cell/GridEditSingleSelectCell.tsx
index a78afe0dfde9a..4c7a9b7c7322d 100644
--- a/packages/grid/x-data-grid/src/components/cell/GridEditSingleSelectCell.tsx
+++ b/packages/grid/x-data-grid/src/components/cell/GridEditSingleSelectCell.tsx
@@ -12,17 +12,21 @@ import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
import { GridEditModes } from '../../models/gridEditRowModel';
import { GridEvents } from '../../models/events/gridEvents';
import { GridColDef, ValueOptions } from '../../models/colDef/gridColDef';
+import { getValueFromValueOptions } from '../panel/filterPanel/filterPanelUtils';
-const renderSingleSelectOptions = (option: ValueOptions) =>
- typeof option === 'object' ? (
-
- ) : (
-
+const renderSingleSelectOptions = (option: ValueOptions, OptionComponent: React.ElementType) => {
+ const isOptionTypeObject = typeof option === 'object';
+
+ const key = isOptionTypeObject ? option.value : option;
+ const value = isOptionTypeObject ? option.value : option;
+ const content = isOptionTypeObject ? option.label : option;
+
+ return (
+
+ {content}
+
);
+};
function GridEditSingleSelectCell(props: GridRenderEditCellParams & Omit) {
const {
@@ -51,6 +55,9 @@ function GridEditSingleSelectCell(props: GridRenderEditCellParams & Omit;
if (typeof colDef.valueOptions === 'function') {
valueOptionsFormatted = colDef.valueOptions!({ id, row, field });
@@ -75,7 +82,9 @@ function GridEditSingleSelectCell(props: GridRenderEditCellParams & Omit) => {
setOpen(false);
const target = event.target as HTMLInputElement;
- const isValid = await api.setEditCellValue({ id, field, value: target.value }, event);
+ // NativeSelect casts the value to a string.
+ const formattedTargetValue = getValueFromValueOptions(target.value, valueOptionsFormatted);
+ const isValid = await api.setEditCellValue({ id, field, value: formattedTargetValue }, event);
if (rootProps.experimentalFeatures?.newEditingApi) {
return;
@@ -134,11 +143,14 @@ function GridEditSingleSelectCell(props: GridRenderEditCellParams & Omit
- {valueOptionsFormatted.map(renderSingleSelectOptions)}
+ {valueOptionsFormatted.map((valueOptions) =>
+ renderSingleSelectOptions(valueOptions, isSelectNative ? 'option' : MenuItem),
+ )}
);
}
diff --git a/packages/grid/x-data-grid/src/components/panel/GridPanel.tsx b/packages/grid/x-data-grid/src/components/panel/GridPanel.tsx
index cf53ad89018ae..07cf2a65bd779 100644
--- a/packages/grid/x-data-grid/src/components/panel/GridPanel.tsx
+++ b/packages/grid/x-data-grid/src/components/panel/GridPanel.tsx
@@ -106,7 +106,7 @@ const GridPanel = React.forwardRef((props, ref)
modifiers={modifiers}
{...other}
>
-
+
{isPlaced && children}
diff --git a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterForm.tsx b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterForm.tsx
index c98cf21a6a98b..fb5e5d29d27dc 100644
--- a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterForm.tsx
+++ b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterForm.tsx
@@ -2,6 +2,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { unstable_composeClasses as composeClasses } from '@mui/material';
import IconButton from '@mui/material/IconButton';
+import MenuItem from '@mui/material/MenuItem';
import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import { SelectChangeEvent } from '@mui/material/Select';
@@ -152,6 +153,10 @@ function GridFilterForm(props: GridFilterFormProps) {
const baseFormControlProps = rootProps.componentsProps?.baseFormControl || {};
+ const baseSelectProps = rootProps.componentsProps?.baseSelect || {};
+ const isBaseSelectNative = baseSelectProps.native ?? true;
+ const OptionComponent = isBaseSelectNative ? 'option' : MenuItem;
+
const sortedFilterableColumns = React.useMemo(() => {
switch (columnsSort) {
case 'asc':
@@ -314,13 +319,13 @@ function GridFilterForm(props: GridFilterFormProps) {
value={multiFilterOperator}
onChange={changeLinkOperator}
disabled={!!disableMultiFilterOperator || linkOperators.length === 1}
- native
+ native={isBaseSelectNative}
{...rootProps.componentsProps?.baseSelect}
>
{linkOperators.map((linkOperator) => (
-
+
))}
@@ -344,13 +349,13 @@ function GridFilterForm(props: GridFilterFormProps) {
label={apiRef.current.getLocaleText('filterPanelColumns')}
value={item.columnField || ''}
onChange={changeColumn}
- native
+ native={isBaseSelectNative}
{...rootProps.componentsProps?.baseSelect}
>
{sortedFilterableColumns.map((col) => (
-
+
))}
@@ -374,17 +379,17 @@ function GridFilterForm(props: GridFilterFormProps) {
id={operatorSelectId}
value={item.operatorValue}
onChange={changeOperator}
- native
+ native={isBaseSelectNative}
inputRef={filterSelectorRef}
{...rootProps.componentsProps?.baseSelect}
>
{currentColumn?.filterOperators?.map((operator) => (
-
+
))}
diff --git a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputBoolean.tsx b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputBoolean.tsx
index 8618a385642bb..453f90aa78079 100644
--- a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputBoolean.tsx
+++ b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputBoolean.tsx
@@ -1,5 +1,6 @@
import * as React from 'react';
import { TextFieldProps } from '@mui/material/TextField';
+import MenuItem from '@mui/material/MenuItem';
import { GridFilterInputValueProps } from './GridFilterInputValueProps';
import { useGridRootProps } from '../../../hooks/utils/useGridRootProps';
@@ -8,6 +9,10 @@ export function GridFilterInputBoolean(props: GridFilterInputValueProps & TextFi
const [filterValueState, setFilterValueState] = React.useState(item.value || '');
const rootProps = useGridRootProps();
+ const baseSelectProps = rootProps.componentsProps?.baseSelect || {};
+ const isSelectNative = baseSelectProps.native ?? true;
+ const OptionComponent = isSelectNative ? 'option' : MenuItem;
+
const onFilterChange = React.useCallback(
(event) => {
const value = event.target.value;
@@ -29,7 +34,9 @@ export function GridFilterInputBoolean(props: GridFilterInputValueProps & TextFi
variant="standard"
select
SelectProps={{
- native: true,
+ native: isSelectNative,
+ displayEmpty: true,
+ ...rootProps.componentsProps?.baseSelect,
}}
InputLabelProps={{
shrink: true,
@@ -38,9 +45,13 @@ export function GridFilterInputBoolean(props: GridFilterInputValueProps & TextFi
{...others}
{...rootProps.componentsProps?.baseTextField}
>
-
-
-
+ {apiRef.current.getLocaleText('filterValueAny')}
+
+ {apiRef.current.getLocaleText('filterValueTrue')}
+
+
+ {apiRef.current.getLocaleText('filterValueFalse')}
+
);
}
diff --git a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputSingleSelect.tsx b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputSingleSelect.tsx
index 5696f5d24eefb..2bb2a55b5aaaa 100644
--- a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputSingleSelect.tsx
+++ b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputSingleSelect.tsx
@@ -2,6 +2,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { TextFieldProps } from '@mui/material/TextField';
import { unstable_useId as useId } from '@mui/material/utils';
+import MenuItem from '@mui/material/MenuItem';
import { GridFilterInputValueProps } from './GridFilterInputValueProps';
import { GridColDef } from '../../../models/colDef/gridColDef';
import { GridApiCommunity } from '../../../models/api/gridApiCommunity';
@@ -11,23 +12,29 @@ import { getValueFromValueOptions } from './filterPanelUtils';
const renderSingleSelectOptions = (
{ valueOptions, valueFormatter, field }: GridColDef,
api: GridApiCommunity,
+ OptionComponent: React.ElementType,
) => {
const iterableColumnValues =
typeof valueOptions === 'function'
? ['', ...valueOptions({ field })]
: ['', ...(valueOptions || [])];
- return iterableColumnValues.map((option) =>
- typeof option === 'object' ? (
-
- ) : (
-
- ),
- );
+ return iterableColumnValues.map((option) => {
+ const isOptionTypeObject = typeof option === 'object';
+
+ const key = isOptionTypeObject ? option.value : option;
+ const value = isOptionTypeObject ? option.value : option;
+
+ const formattedValue =
+ valueFormatter && option !== '' ? valueFormatter({ value: option, field, api }) : option;
+ const content = isOptionTypeObject ? option.label : formattedValue;
+
+ return (
+
+ {content}
+
+ );
+ });
};
export type GridFilterInputSingleSelectProps = GridFilterInputValueProps &
@@ -39,6 +46,9 @@ function GridFilterInputSingleSelect(props: GridFilterInputSingleSelectProps) {
const id = useId();
const rootProps = useGridRootProps();
+ const baseSelectProps = rootProps.componentsProps?.baseSelect || {};
+ const isSelectNative = baseSelectProps.native ?? true;
+
const currentColumn = item.columnField ? apiRef.current.getColumn(item.columnField) : null;
const currentValueOptions = React.useMemo(() => {
@@ -94,12 +104,17 @@ function GridFilterInputSingleSelect(props: GridFilterInputSingleSelectProps) {
inputRef={focusElementRef}
select
SelectProps={{
- native: true,
+ native: isSelectNative,
+ ...rootProps.componentsProps?.baseSelect,
}}
{...others}
{...rootProps.componentsProps?.baseTextField}
>
- {renderSingleSelectOptions(apiRef.current.getColumn(item.columnField), apiRef.current)}
+ {renderSingleSelectOptions(
+ apiRef.current.getColumn(item.columnField),
+ apiRef.current,
+ isSelectNative ? 'option' : MenuItem,
+ )}
);
}
diff --git a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx
index 6477e43d9d41e..97843d2f94dde 100644
--- a/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx
+++ b/packages/grid/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx
@@ -2,6 +2,7 @@ import * as React from 'react';
import PropTypes from 'prop-types';
import { TextFieldProps } from '@mui/material/TextField';
import { unstable_useId as useId } from '@mui/material/utils';
+import MenuItem from '@mui/material/MenuItem';
import { GridLoadIcon } from '../../icons';
import { GridFilterInputValueProps } from './GridFilterInputValueProps';
import { GridColDef } from '../../../models/colDef/gridColDef';
@@ -24,23 +25,29 @@ function warnDeprecatedTypeSupport(type: string) {
const renderSingleSelectOptions = (
{ valueOptions, valueFormatter, field }: GridColDef,
api: GridApiCommunity,
+ OptionComponent: React.ElementType,
) => {
const iterableColumnValues =
typeof valueOptions === 'function'
? ['', ...valueOptions({ field })]
: ['', ...(valueOptions || [])];
- return iterableColumnValues.map((option) =>
- typeof option === 'object' ? (
-
- ) : (
-
- ),
- );
+ return iterableColumnValues.map((option) => {
+ const isOptionTypeObject = typeof option === 'object';
+
+ const key = isOptionTypeObject ? option.value : option;
+ const value = isOptionTypeObject ? option.value : option;
+
+ const formattedValue =
+ valueFormatter && option !== '' ? valueFormatter({ value: option, field, api }) : option;
+ const content = isOptionTypeObject ? option.label : formattedValue;
+
+ return (
+
+ {content}
+
+ );
+ });
};
export const SUBMIT_FILTER_STROKE_TIME = 500;
@@ -63,16 +70,22 @@ function GridFilterInputValue(props: GridTypeFilterInputValueProps & TextFieldPr
const [applying, setIsApplying] = React.useState(false);
const id = useId();
const rootProps = useGridRootProps();
+
+ const baseSelectProps = rootProps.componentsProps?.baseSelect || {};
+ const isSelectNative = baseSelectProps.native ?? true;
+
const singleSelectProps: TextFieldProps =
type === 'singleSelect'
? {
select: true,
SelectProps: {
- native: true,
+ native: isSelectNative,
+ ...rootProps.componentsProps?.baseSelect,
},
children: renderSingleSelectOptions(
apiRef.current.getColumn(item.columnField),
apiRef.current,
+ isSelectNative ? 'option' : MenuItem,
),
}
: {};