diff --git a/packages/material-renderers/src/controls/MaterialAnyOfStringOrEnumControl.tsx b/packages/material-renderers/src/controls/MaterialAnyOfStringOrEnumControl.tsx
index 7cb128f8b..288f84cc6 100644
--- a/packages/material-renderers/src/controls/MaterialAnyOfStringOrEnumControl.tsx
+++ b/packages/material-renderers/src/controls/MaterialAnyOfStringOrEnumControl.tsx
@@ -38,7 +38,12 @@ import { Control, withJsonFormsControlProps } from '@jsonforms/react';
 import { InputBaseComponentProps } from '@mui/material';
 import merge from 'lodash/merge';
 import React, { useMemo } from 'react';
-import { useDebouncedChange, useInputComponent, WithInputProps } from '../util';
+import {
+  useDebouncedChange,
+  useInputComponent,
+  WithInputProps,
+  useFocus,
+} from '../util';
 import { MaterialInputControl } from './MaterialInputControl';
 
 const findEnumSchema = (schemas: JsonSchema[]) =>
@@ -51,6 +56,7 @@ const findTextSchema = (schemas: JsonSchema[]) =>
 const MuiAutocompleteInputText = (
   props: EnumCellProps & WithClassname & WithInputProps
 ) => {
+  const [focused, onFocus, onBlur] = useFocus();
   const {
     data,
     config,
@@ -83,12 +89,13 @@ const MuiAutocompleteInputText = (
     propMemo.list = props.id + 'datalist';
     return propMemo;
   }, [appliedUiSchemaOptions, props.id]);
-  const [inputText, onChange] = useDebouncedChange(
+  const [inputText, onChange] = useDebouncedChange({
     handleChange,
-    '',
     data,
-    path
-  );
+    path,
+    focused,
+    flushOnBlur: true,
+  });
 
   const dataList = (
     <datalist id={props.id + 'datalist'}>
@@ -102,6 +109,8 @@ const MuiAutocompleteInputText = (
       type='text'
       value={inputText}
       onChange={onChange}
+      onFocus={onFocus}
+      onBlur={onBlur}
       className={className}
       id={id}
       label={label}
diff --git a/packages/material-renderers/src/controls/MaterialNativeControl.tsx b/packages/material-renderers/src/controls/MaterialNativeControl.tsx
index 358d45f71..b538a7e5e 100644
--- a/packages/material-renderers/src/controls/MaterialNativeControl.tsx
+++ b/packages/material-renderers/src/controls/MaterialNativeControl.tsx
@@ -1,19 +1,19 @@
 /*
   The MIT License
-  
+
   Copyright (c) 2017-2019 EclipseSource Munich
   https://github.com/eclipsesource/jsonforms
-  
+
   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:
-  
+
   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.
-  
+
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -56,12 +56,11 @@ export const MaterialNativeControl = (props: ControlProps) => {
   } = props;
   const isValid = errors.length === 0;
   const appliedUiSchemaOptions = merge({}, config, props.uischema.options);
-  const [inputValue, onChange] = useDebouncedChange(
+  const [inputValue, onChange] = useDebouncedChange({
     handleChange,
-    '',
     data,
-    path
-  );
+    path,
+  });
   const fieldType = appliedUiSchemaOptions.format ?? schema.format;
   const showDescription = !isDescriptionHidden(
     visible,
diff --git a/packages/material-renderers/src/mui-controls/MuiInputInteger.tsx b/packages/material-renderers/src/mui-controls/MuiInputInteger.tsx
index 4d2f8f376..2fc2db81d 100644
--- a/packages/material-renderers/src/mui-controls/MuiInputInteger.tsx
+++ b/packages/material-renderers/src/mui-controls/MuiInputInteger.tsx
@@ -25,7 +25,12 @@
 import React from 'react';
 import { CellProps, WithClassname } from '@jsonforms/core';
 import merge from 'lodash/merge';
-import { useDebouncedChange, useInputComponent, WithInputProps } from '../util';
+import {
+  useDebouncedChange,
+  useInputComponent,
+  WithInputProps,
+  useFocus,
+} from '../util';
 
 const toNumber = (value: string) =>
   value === '' ? undefined : parseInt(value, 10);
@@ -34,6 +39,7 @@ const eventToValue = (ev: any) => toNumber(ev.target.value);
 export const MuiInputInteger = React.memo(function MuiInputInteger(
   props: CellProps & WithClassname & WithInputProps
 ) {
+  const [focused, onFocus, onBlur] = useFocus();
   const {
     data,
     className,
@@ -51,19 +57,22 @@ export const MuiInputInteger = React.memo(function MuiInputInteger(
 
   const appliedUiSchemaOptions = merge({}, config, uischema.options);
 
-  const [inputValue, onChange] = useDebouncedChange(
+  const [inputValue, onChange] = useDebouncedChange({
     handleChange,
-    '',
     data,
     path,
-    eventToValue
-  );
+    eventToValue,
+    focused,
+    flushOnBlur: true,
+  });
 
   return (
     <InputComponent
       label={label}
       type='number'
       value={inputValue}
+      onFocus={onFocus}
+      onBlur={onBlur}
       onChange={onChange}
       className={className}
       id={id}
diff --git a/packages/material-renderers/src/mui-controls/MuiInputNumber.tsx b/packages/material-renderers/src/mui-controls/MuiInputNumber.tsx
index 1d626f6b1..a9c082c3c 100644
--- a/packages/material-renderers/src/mui-controls/MuiInputNumber.tsx
+++ b/packages/material-renderers/src/mui-controls/MuiInputNumber.tsx
@@ -25,7 +25,12 @@
 import React from 'react';
 import { CellProps, WithClassname } from '@jsonforms/core';
 import merge from 'lodash/merge';
-import { useDebouncedChange, useInputComponent, WithInputProps } from '../util';
+import {
+  useDebouncedChange,
+  useInputComponent,
+  WithInputProps,
+  useFocus,
+} from '../util';
 
 const toNumber = (value: string) =>
   value === '' ? undefined : parseFloat(value);
@@ -33,6 +38,7 @@ const eventToValue = (ev: any) => toNumber(ev.target.value);
 export const MuiInputNumber = React.memo(function MuiInputNumber(
   props: CellProps & WithClassname & WithInputProps
 ) {
+  const [focused, onFocus, onBlur] = useFocus();
   const {
     data,
     className,
@@ -49,13 +55,14 @@ export const MuiInputNumber = React.memo(function MuiInputNumber(
   const inputProps = { step: '0.1' };
 
   const appliedUiSchemaOptions = merge({}, config, uischema.options);
-  const [inputValue, onChange] = useDebouncedChange(
+  const [inputValue, onChange] = useDebouncedChange({
     handleChange,
-    '',
     data,
     path,
-    eventToValue
-  );
+    eventToValue,
+    focused,
+    flushOnBlur: true,
+  });
 
   return (
     <InputComponent
@@ -63,6 +70,8 @@ export const MuiInputNumber = React.memo(function MuiInputNumber(
       label={label}
       value={inputValue}
       onChange={onChange}
+      onFocus={onFocus}
+      onBlur={onBlur}
       className={className}
       id={id}
       disabled={!enabled}
diff --git a/packages/material-renderers/src/mui-controls/MuiInputNumberFormat.tsx b/packages/material-renderers/src/mui-controls/MuiInputNumberFormat.tsx
index a7e8bf686..9b1d3296e 100644
--- a/packages/material-renderers/src/mui-controls/MuiInputNumberFormat.tsx
+++ b/packages/material-renderers/src/mui-controls/MuiInputNumberFormat.tsx
@@ -25,11 +25,17 @@
 import React, { useCallback } from 'react';
 import { CellProps, Formatted, WithClassname } from '@jsonforms/core';
 import merge from 'lodash/merge';
-import { useDebouncedChange, useInputComponent, WithInputProps } from '../util';
+import {
+  useDebouncedChange,
+  useInputComponent,
+  WithInputProps,
+  useFocus,
+} from '../util';
 
 export const MuiInputNumberFormat = React.memo(function MuiInputNumberFormat(
   props: CellProps & WithClassname & Formatted<number> & WithInputProps
 ) {
+  const [focused, onFocus, onBlur] = useFocus();
   const {
     className,
     id,
@@ -57,19 +63,22 @@ export const MuiInputNumberFormat = React.memo(function MuiInputNumberFormat(
     (ev: any) => props.fromFormatted(ev.currentTarget.value),
     [props.fromFormatted]
   );
-  const [inputValue, onChange] = useDebouncedChange(
+  const [inputValue, onChange] = useDebouncedChange({
     handleChange,
-    '',
-    formattedNumber,
+    data: formattedNumber,
     path,
-    validStringNumber
-  );
+    eventToValue: validStringNumber,
+    focused,
+    flushOnBlur: true,
+  });
 
   return (
     <InputComponent
       type='text'
       value={inputValue}
       onChange={onChange}
+      onFocus={onFocus}
+      onBlur={onBlur}
       className={className}
       id={id}
       label={label}
diff --git a/packages/material-renderers/src/mui-controls/MuiInputText.tsx b/packages/material-renderers/src/mui-controls/MuiInputText.tsx
index de4845af4..e33c1a126 100644
--- a/packages/material-renderers/src/mui-controls/MuiInputText.tsx
+++ b/packages/material-renderers/src/mui-controls/MuiInputText.tsx
@@ -38,6 +38,7 @@ import {
   WithInputProps,
   useDebouncedChange,
   useInputComponent,
+  useFocus,
 } from '../util';
 
 interface MuiTextInputProps {
@@ -51,6 +52,7 @@ const eventToValue = (ev: any) =>
 export const MuiInputText = React.memo(function MuiInputText(
   props: CellProps & WithClassname & MuiTextInputProps & WithInputProps
 ) {
+  const [focused, onFocus, onBlur] = useFocus();
   const [showAdornment, setShowAdornment] = useState(false);
   const {
     data,
@@ -83,13 +85,14 @@ export const MuiInputText = React.memo(function MuiInputText(
     inputProps.size = maxLength;
   }
 
-  const [inputText, onChange, onClear] = useDebouncedChange(
+  const [inputText, onChange, onClear] = useDebouncedChange({
     handleChange,
-    '',
     data,
     path,
-    eventToValue
-  );
+    eventToValue,
+    flushOnBlur: true,
+    focused,
+  });
   const onPointerEnter = () => setShowAdornment(true);
   const onPointerLeave = () => setShowAdornment(false);
 
@@ -109,6 +112,8 @@ export const MuiInputText = React.memo(function MuiInputText(
       value={inputText}
       onChange={onChange}
       className={className}
+      onBlur={onBlur}
+      onFocus={onFocus}
       id={id}
       disabled={!enabled}
       autoFocus={appliedUiSchemaOptions.focus}
diff --git a/packages/material-renderers/src/mui-controls/MuiInputTime.tsx b/packages/material-renderers/src/mui-controls/MuiInputTime.tsx
index 0a7c1da8e..a5b4483ca 100644
--- a/packages/material-renderers/src/mui-controls/MuiInputTime.tsx
+++ b/packages/material-renderers/src/mui-controls/MuiInputTime.tsx
@@ -44,12 +44,11 @@ export const MuiInputTime = React.memo(function MuiInputTime(
   } = props;
   const InputComponent = useInputComponent();
   const appliedUiSchemaOptions = merge({}, config, uischema.options);
-  const [inputValue, onChange] = useDebouncedChange(
+  const [inputValue, onChange] = useDebouncedChange({
     handleChange,
-    '',
     data,
-    path
-  );
+    path,
+  });
 
   return (
     <InputComponent
diff --git a/packages/material-renderers/src/util/debounce.ts b/packages/material-renderers/src/util/debounce.ts
index 2971df827..2d0099ccc 100644
--- a/packages/material-renderers/src/util/debounce.ts
+++ b/packages/material-renderers/src/util/debounce.ts
@@ -1,19 +1,19 @@
 /*
   The MIT License
-  
+
   Copyright (c) 2021 EclipseSource Munich
   https://github.com/eclipsesource/jsonforms
-  
+
   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:
-  
+
   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.
-  
+
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -25,15 +25,27 @@
 import debounce from 'lodash/debounce';
 import { useState, useCallback, useEffect } from 'react';
 
-const eventToValue = (ev: any) => ev.target.value;
-export const useDebouncedChange = (
-  handleChange: (path: string, value: any) => void,
-  defaultValue: any,
-  data: any,
-  path: string,
-  eventToValueFunction: (ev: any) => any = eventToValue,
-  timeout = 300
-): [any, React.ChangeEventHandler, () => void] => {
+const defaultEventToValue = (ev: any) => ev.target.value;
+interface DebouncedChangeParams {
+  handleChange: (path: string, value: any) => void;
+  data: any;
+  path: string;
+  eventToValue?: (ev: any) => any;
+  defaultValue?: any;
+  flushOnBlur?: boolean;
+  focused?: boolean;
+  timeout?: number;
+}
+export const useDebouncedChange = ({
+  handleChange,
+  data,
+  path,
+  eventToValue = undefined,
+  defaultValue = '',
+  flushOnBlur = false,
+  focused = false,
+  timeout = 300,
+}: DebouncedChangeParams): [any, React.ChangeEventHandler, () => void] => {
   const [input, setInput] = useState(data ?? defaultValue);
   useEffect(() => {
     setInput(data ?? defaultValue);
@@ -42,13 +54,20 @@ export const useDebouncedChange = (
     debounce((newValue: string) => handleChange(path, newValue), timeout),
     [handleChange, path, timeout]
   );
+  useEffect(() => {
+    if (!focused && flushOnBlur) {
+      debouncedUpdate.flush();
+    }
+  }, [focused, flushOnBlur, debouncedUpdate]);
   const onChange = useCallback(
     (ev: any) => {
-      const newValue = eventToValueFunction(ev);
+      const newValue = eventToValue
+        ? eventToValue(ev)
+        : defaultEventToValue(ev);
       setInput(newValue ?? defaultValue);
       debouncedUpdate(newValue);
     },
-    [debouncedUpdate, eventToValueFunction]
+    [debouncedUpdate, eventToValue]
   );
   const onClear = useCallback(() => {
     setInput(defaultValue);