diff --git a/packages/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx b/packages/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx index 1d40414b972ec..657e2effad511 100644 --- a/packages/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx +++ b/packages/x-data-grid-pro/src/components/headerFiltering/GridHeaderFilterCell.tsx @@ -89,7 +89,7 @@ const useUtilityClasses = (ownerState: OwnerState) => { return composeClasses(slots, getDataGridUtilityClass, classes); }; -const dateSx = { +const emptyFieldSx = { [`& input[value=""]:not(:focus)`]: { color: 'transparent' }, }; const defaultInputComponents: { [key in GridColType]: React.JSXElementConstructor | null } = { @@ -366,7 +366,11 @@ const GridHeaderFilterCell = forwardRef - Filter', () => { expect(getRows({ operator: 'is', value: null })).to.deep.equal(ALL_ROWS); expect(getRows({ operator: 'is', value: 'test' })).to.deep.equal(ALL_ROWS); // Ignores invalid values }); + + it('should allow temporary invalid values while updating the number filter', async () => { + clock.restore(); + const changeSpy = spy(); + const { user } = render( + , + ); + expect(getColumnValues(0)).to.deep.equal(['-10', '10', '100', '1,000']); + + const filterCell = getColumnHeaderCell(0, 1); + await user.click(within(filterCell).getByLabelText('Operator')); + await user.click(screen.getByRole('menuitem', { name: 'Greater than' })); + + const input = within(filterCell).getByLabelText('Greater than'); + await user.click(input); + expect(input).toHaveFocus(); + + await user.keyboard('0'); + await waitFor(() => expect(getColumnValues(0)).to.deep.equal(['10', '100', '1,000'])); + expect(changeSpy.lastCall.args[0].items[0].value).to.equal(0); + + await user.keyboard('.'); + await waitFor(() => expect(getColumnValues(0)).to.deep.equal(['10', '100', '1,000'])); + expect(changeSpy.lastCall.args[0].items[0].value).to.equal(0); // 0. + + await user.keyboard('1'); + await waitFor(() => expect(getColumnValues(0)).to.deep.equal(['10', '100', '1,000'])); + await waitFor(() => expect(changeSpy.lastCall.args[0].items[0].value).to.equal(0.1)); // 0.1 + + await user.keyboard('e'); + await waitFor(() => expect(getColumnValues(0)).to.deep.equal(['-10', '10', '100', '1,000'])); + expect(changeSpy.lastCall.args[0].items[0].value).to.equal(undefined); // 0.1e + + await user.keyboard('2'); + await waitFor(() => expect(getColumnValues(0)).to.deep.equal(['100', '1,000'])); + expect(changeSpy.lastCall.args[0].items[0].value).to.equal(10); // 0.1e2 + }); }); describe('Read-only filters', () => { diff --git a/packages/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx b/packages/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx index 32d76d2516114..826e0cef68a4f 100644 --- a/packages/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx +++ b/packages/x-data-grid/src/components/panel/filterPanel/GridFilterInputValue.tsx @@ -37,8 +37,8 @@ function GridFilterInputValue(props: GridTypeFilterInputValueProps) { } = props; const filterTimeout = useTimeout(); - const [filterValueState, setFilterValueState] = React.useState( - sanitizeFilterItemValue(item.value, type), + const [filterValueState, setFilterValueState] = React.useState( + sanitizeFilterItemValue(item.value), ); const [applying, setIsApplying] = React.useState(false); const id = useId(); @@ -46,14 +46,14 @@ function GridFilterInputValue(props: GridTypeFilterInputValueProps) { const onFilterChange = React.useCallback( (event: React.ChangeEvent) => { - const value = sanitizeFilterItemValue(event.target.value, type); - setFilterValueState(value); + const value = sanitizeFilterItemValue(event.target.value); + setFilterValueState(value); setIsApplying(true); filterTimeout.start(rootProps.filterDebounceMs, () => { const newItem = { ...item, - value, + value: type === 'number' && !Number.isNaN(Number(value)) ? Number(value) : value, fromInput: id!, }; applyValue(newItem); @@ -66,16 +66,16 @@ function GridFilterInputValue(props: GridTypeFilterInputValueProps) { React.useEffect(() => { const itemPlusTag = item as ItemPlusTag; if (itemPlusTag.fromInput !== id || item.value == null) { - setFilterValueState(sanitizeFilterItemValue(item.value, type)); + setFilterValueState(sanitizeFilterItemValue(item.value)); } - }, [id, item, type]); + }, [id, item]); return (