From 9fee69b69b6d3669518d3380850f4462927551b0 Mon Sep 17 00:00:00 2001
From: sai chand <60743144+sai6855@users.noreply.github.com>
Date: Mon, 15 Apr 2024 19:03:12 +0530
Subject: [PATCH] [DataGrid] Fix calling onCellEditStop on error (#12747)

Signed-off-by: Andrew Cherniavskii <andrew.cherniavskii@gmail.com>
Co-authored-by: Andrew Cherniavskii <andrew.cherniavskii@gmail.com>
---
 .../tests/cellEditing.DataGridPro.test.tsx    | 27 +++++++++++++++++++
 .../features/editing/useGridCellEditing.ts    | 17 +++++++++++-
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx
index 6c5ccec2e3392..0e495c3794828 100644
--- a/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx
+++ b/packages/x-data-grid-pro/src/tests/cellEditing.DataGridPro.test.tsx
@@ -190,6 +190,33 @@ describe('<DataGridPro /> - Cell editing', () => {
         });
       });
 
+      it('should not publish onCellEditStop if field has error', async () => {
+        columnProps.preProcessEditCellProps = spy(({ props }: GridPreProcessEditCellProps) => ({
+          ...props,
+          error: true,
+        }));
+
+        const handleEditCellStop = spy();
+
+        render(<TestCase onCellEditStop={handleEditCellStop} />);
+        act(() => apiRef.current.startCellEditMode({ id: 0, field: 'currencyPair' }));
+        await act(() =>
+          apiRef.current.setEditCellValue({
+            id: 0,
+            field: 'currencyPair',
+            value: 'USD GBP',
+          }),
+        );
+        const cell = getCell(0, 1);
+        cell.focus();
+
+        await act(() => {
+          fireEvent.keyDown(cell, { key: 'Enter' });
+        });
+
+        expect(handleEditCellStop.callCount).to.equal(0);
+      });
+
       it('should pass to renderEditCell the props returned by preProcessEditCellProps', async () => {
         columnProps.preProcessEditCellProps = ({ props }: GridPreProcessEditCellProps) => ({
           ...props,
diff --git a/packages/x-data-grid/src/hooks/features/editing/useGridCellEditing.ts b/packages/x-data-grid/src/hooks/features/editing/useGridCellEditing.ts
index d1f4f06b5da9c..8220068b7d35f 100644
--- a/packages/x-data-grid/src/hooks/features/editing/useGridCellEditing.ts
+++ b/packages/x-data-grid/src/hooks/features/editing/useGridCellEditing.ts
@@ -234,6 +234,21 @@ export const useGridCellEditing = (
     [apiRef],
   );
 
+  const runIfNoFieldErrors =
+    <Args extends Parameters<GridEventListener<'cellEditStop'>>>(
+      callback?: (...args: Args) => void,
+    ) =>
+    async (...args: Args) => {
+      if (callback) {
+        const { id, field } = args[0];
+        const editRowsState = apiRef.current.state.editRows;
+        const hasFieldErrors = editRowsState[id][field]?.error;
+        if (!hasFieldErrors) {
+          callback(...args);
+        }
+      }
+    };
+
   useGridApiEventHandler(apiRef, 'cellDoubleClick', runIfEditModeIsCell(handleCellDoubleClick));
   useGridApiEventHandler(apiRef, 'cellFocusOut', runIfEditModeIsCell(handleCellFocusOut));
   useGridApiEventHandler(apiRef, 'cellKeyDown', runIfEditModeIsCell(handleCellKeyDown));
@@ -242,7 +257,7 @@ export const useGridCellEditing = (
   useGridApiEventHandler(apiRef, 'cellEditStop', runIfEditModeIsCell(handleCellEditStop));
 
   useGridApiOptionHandler(apiRef, 'cellEditStart', props.onCellEditStart);
-  useGridApiOptionHandler(apiRef, 'cellEditStop', props.onCellEditStop);
+  useGridApiOptionHandler(apiRef, 'cellEditStop', runIfNoFieldErrors(props.onCellEditStop));
 
   const getCellMode = React.useCallback<GridCellEditingApi['getCellMode']>(
     (id, field) => {