Skip to content

Commit

Permalink
Merge pull request #9730 from yanchesky/fix-onblur-function-parameter
Browse files Browse the repository at this point in the history
Fixed onBlur callback on NumberInput and AutocompleteInput
  • Loading branch information
slax57 authored Feb 21, 2025
2 parents e547f7f + 674ee21 commit 7f8333a
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 22 deletions.
9 changes: 7 additions & 2 deletions packages/ra-core/src/form/useInput.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactElement, useEffect, useId } from 'react';
import { ReactElement, useEffect, useId, FocusEvent } from 'react';
import {
ControllerFieldState,
ControllerRenderProps,
Expand All @@ -7,6 +7,7 @@ import {
UseControllerReturn,
UseFormStateReturn,
} from 'react-hook-form';
import type { EditorEvents } from '@tiptap/react';
import get from 'lodash/get';

import { useRecordContext } from '../controller';
Expand Down Expand Up @@ -168,7 +169,11 @@ export type InputProps<ValueType = any> = Omit<
export type UseInputValue = {
id: string;
isRequired: boolean;
field: ControllerRenderProps;
field: Omit<ControllerRenderProps, 'onBlur'> & {
onBlur: (
event?: FocusEvent<HTMLElement> | EditorEvents['blur']
) => void;
};
formState: UseFormStateReturn<Record<string, string>>;
fieldState: ControllerFieldState;
};
26 changes: 26 additions & 0 deletions packages/ra-ui-materialui/src/input/AutocompleteInput.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1565,6 +1565,32 @@ describe('<AutocompleteInput />', () => {
});
});

it('should pass the event object to the onBlur callback', async () => {
const onBlur = jest.fn();
render(
<AdminContext dataProvider={testDataProvider()}>
<ResourceContextProvider value="users">
<SimpleForm onSubmit={jest.fn()}>
<AutocompleteInput
{...defaultProps}
choices={[{ id: 0, name: 'foo' }]}
onBlur={onBlur}
/>
</SimpleForm>
</ResourceContextProvider>
</AdminContext>
);
const input = screen.getByLabelText(
'resources.users.fields.role'
) as HTMLInputElement;

fireEvent.blur(input);

expect(onBlur).toHaveBeenCalledWith(
expect.objectContaining({ type: 'blur' })
);
});

describe('Inside <ReferenceInput>', () => {
it('should work inside a ReferenceInput field', async () => {
render(<InsideReferenceInput />);
Expand Down
37 changes: 20 additions & 17 deletions packages/ra-ui-materialui/src/input/AutocompleteInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -438,24 +438,27 @@ If you provided a React element for the optionText prop, you must also provide t
]
);

const finalOnBlur = useCallback((): void => {
if (clearOnBlur && !multiple) {
const optionLabel = getOptionLabel(selectedChoice);
if (!isEqual(optionLabel, filterValue)) {
setFilterValue(optionLabel);
debouncedSetFilter('');
const finalOnBlur = useCallback(
(event): void => {
if (clearOnBlur && !multiple) {
const optionLabel = getOptionLabel(selectedChoice);
if (!isEqual(optionLabel, filterValue)) {
setFilterValue(optionLabel);
debouncedSetFilter('');
}
}
}
field.onBlur();
}, [
clearOnBlur,
field,
getOptionLabel,
selectedChoice,
filterValue,
debouncedSetFilter,
multiple,
]);
field.onBlur(event);
},
[
clearOnBlur,
field,
getOptionLabel,
selectedChoice,
filterValue,
debouncedSetFilter,
multiple,
]
);

useEffect(() => {
if (!multiple) {
Expand Down
4 changes: 3 additions & 1 deletion packages/ra-ui-materialui/src/input/NumberInput.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,9 @@ describe('<NumberInput />', () => {
);
const input = screen.getByLabelText('resources.posts.fields.views');
fireEvent.blur(input);
expect(onBlur).toHaveBeenCalled();
expect(onBlur).toHaveBeenCalledWith(
expect.objectContaining({ type: 'blur' })
);
});

it('should display error message onBlur if required', async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/ra-ui-materialui/src/input/NumberInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ export const NumberInput = ({
hasFocus.current = true;
};

const handleBlur = () => {
const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
if (onBlurFromField) {
onBlurFromField();
onBlurFromField(event);
}
hasFocus.current = false;
const stringValue = format(field.value);
Expand Down

0 comments on commit 7f8333a

Please sign in to comment.