Skip to content

Commit 7f8333a

Browse files
authored
Merge pull request #9730 from yanchesky/fix-onblur-function-parameter
Fixed onBlur callback on NumberInput and AutocompleteInput
2 parents e547f7f + 674ee21 commit 7f8333a

File tree

5 files changed

+58
-22
lines changed

5 files changed

+58
-22
lines changed

packages/ra-core/src/form/useInput.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ReactElement, useEffect, useId } from 'react';
1+
import { ReactElement, useEffect, useId, FocusEvent } from 'react';
22
import {
33
ControllerFieldState,
44
ControllerRenderProps,
@@ -7,6 +7,7 @@ import {
77
UseControllerReturn,
88
UseFormStateReturn,
99
} from 'react-hook-form';
10+
import type { EditorEvents } from '@tiptap/react';
1011
import get from 'lodash/get';
1112

1213
import { useRecordContext } from '../controller';
@@ -168,7 +169,11 @@ export type InputProps<ValueType = any> = Omit<
168169
export type UseInputValue = {
169170
id: string;
170171
isRequired: boolean;
171-
field: ControllerRenderProps;
172+
field: Omit<ControllerRenderProps, 'onBlur'> & {
173+
onBlur: (
174+
event?: FocusEvent<HTMLElement> | EditorEvents['blur']
175+
) => void;
176+
};
172177
formState: UseFormStateReturn<Record<string, string>>;
173178
fieldState: ControllerFieldState;
174179
};

packages/ra-ui-materialui/src/input/AutocompleteInput.spec.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,32 @@ describe('<AutocompleteInput />', () => {
15651565
});
15661566
});
15671567

1568+
it('should pass the event object to the onBlur callback', async () => {
1569+
const onBlur = jest.fn();
1570+
render(
1571+
<AdminContext dataProvider={testDataProvider()}>
1572+
<ResourceContextProvider value="users">
1573+
<SimpleForm onSubmit={jest.fn()}>
1574+
<AutocompleteInput
1575+
{...defaultProps}
1576+
choices={[{ id: 0, name: 'foo' }]}
1577+
onBlur={onBlur}
1578+
/>
1579+
</SimpleForm>
1580+
</ResourceContextProvider>
1581+
</AdminContext>
1582+
);
1583+
const input = screen.getByLabelText(
1584+
'resources.users.fields.role'
1585+
) as HTMLInputElement;
1586+
1587+
fireEvent.blur(input);
1588+
1589+
expect(onBlur).toHaveBeenCalledWith(
1590+
expect.objectContaining({ type: 'blur' })
1591+
);
1592+
});
1593+
15681594
describe('Inside <ReferenceInput>', () => {
15691595
it('should work inside a ReferenceInput field', async () => {
15701596
render(<InsideReferenceInput />);

packages/ra-ui-materialui/src/input/AutocompleteInput.tsx

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -438,24 +438,27 @@ If you provided a React element for the optionText prop, you must also provide t
438438
]
439439
);
440440

441-
const finalOnBlur = useCallback((): void => {
442-
if (clearOnBlur && !multiple) {
443-
const optionLabel = getOptionLabel(selectedChoice);
444-
if (!isEqual(optionLabel, filterValue)) {
445-
setFilterValue(optionLabel);
446-
debouncedSetFilter('');
441+
const finalOnBlur = useCallback(
442+
(event): void => {
443+
if (clearOnBlur && !multiple) {
444+
const optionLabel = getOptionLabel(selectedChoice);
445+
if (!isEqual(optionLabel, filterValue)) {
446+
setFilterValue(optionLabel);
447+
debouncedSetFilter('');
448+
}
447449
}
448-
}
449-
field.onBlur();
450-
}, [
451-
clearOnBlur,
452-
field,
453-
getOptionLabel,
454-
selectedChoice,
455-
filterValue,
456-
debouncedSetFilter,
457-
multiple,
458-
]);
450+
field.onBlur(event);
451+
},
452+
[
453+
clearOnBlur,
454+
field,
455+
getOptionLabel,
456+
selectedChoice,
457+
filterValue,
458+
debouncedSetFilter,
459+
multiple,
460+
]
461+
);
459462

460463
useEffect(() => {
461464
if (!multiple) {

packages/ra-ui-materialui/src/input/NumberInput.spec.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,9 @@ describe('<NumberInput />', () => {
557557
);
558558
const input = screen.getByLabelText('resources.posts.fields.views');
559559
fireEvent.blur(input);
560-
expect(onBlur).toHaveBeenCalled();
560+
expect(onBlur).toHaveBeenCalledWith(
561+
expect.objectContaining({ type: 'blur' })
562+
);
561563
});
562564

563565
it('should display error message onBlur if required', async () => {

packages/ra-ui-materialui/src/input/NumberInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ export const NumberInput = ({
111111
hasFocus.current = true;
112112
};
113113

114-
const handleBlur = () => {
114+
const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
115115
if (onBlurFromField) {
116-
onBlurFromField();
116+
onBlurFromField(event);
117117
}
118118
hasFocus.current = false;
119119
const stringValue = format(field.value);

0 commit comments

Comments
 (0)