Skip to content

Commit 3fcf88e

Browse files
authored
Merge pull request #8123 from marmelab/fix-autocomplete-clearonblur
Fix AutocompleteInput `clearOnBlur` has no effect
2 parents a8918d8 + 7069739 commit 3fcf88e

File tree

2 files changed

+38
-3
lines changed

2 files changed

+38
-3
lines changed

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

+27-1
Original file line numberDiff line numberDiff line change
@@ -875,7 +875,7 @@ describe('<AutocompleteInput />', () => {
875875
fireEvent.blur(input);
876876
fireEvent.focus(input);
877877
await waitFor(() => {
878-
expect(screen.queryAllByRole('option').length).toEqual(2);
878+
expect(screen.queryAllByRole('option').length).toEqual(3);
879879
});
880880
});
881881

@@ -1234,4 +1234,30 @@ describe('<AutocompleteInput />', () => {
12341234
screen.getByText(/Dalmatian #1050/);
12351235
});
12361236
});
1237+
1238+
it('should clear the input when its blurred, having an unmatching selection and clearOnBlur prop is true', async () => {
1239+
render(
1240+
<AdminContext dataProvider={testDataProvider()}>
1241+
<SimpleForm onSubmit={jest.fn()}>
1242+
<AutocompleteInput
1243+
{...defaultProps}
1244+
clearOnBlur
1245+
choices={[
1246+
{ id: 1, name: 'ab' },
1247+
{ id: 2, name: 'abc' },
1248+
{ id: 3, name: '123' },
1249+
]}
1250+
/>
1251+
</SimpleForm>
1252+
</AdminContext>
1253+
);
1254+
const input = screen.getByLabelText(
1255+
'resources.users.fields.role'
1256+
) as HTMLInputElement;
1257+
fireEvent.change(input, { target: { value: 'no match' } });
1258+
fireEvent.blur(input);
1259+
await waitFor(() => {
1260+
expect(input.value).toEqual('');
1261+
});
1262+
});
12371263
});

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

+11-2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ export const AutocompleteInput = <
127127
const {
128128
choices: choicesProp,
129129
className,
130+
clearOnBlur = true,
130131
clearText = 'ra.action.clear_input_value',
131132
closeText = 'ra.action.close',
132133
create,
@@ -350,6 +351,14 @@ If you provided a React element for the optionText prop, you must also provide t
350351
[getChoiceText, inputText, createId]
351352
);
352353

354+
const finalOnBlur = useCallback((): void => {
355+
if (clearOnBlur) {
356+
const optionLabel = getOptionLabel(selectedChoice);
357+
setFilterValue(optionLabel);
358+
}
359+
field.onBlur();
360+
}, [clearOnBlur, field, selectedChoice, getOptionLabel]);
361+
353362
useEffect(() => {
354363
if (!multiple) {
355364
const optionLabel = getOptionLabel(selectedChoice);
@@ -523,7 +532,7 @@ If you provided a React element for the optionText prop, you must also provide t
523532
: noOptionsText
524533
}
525534
selectOnFocus
526-
clearOnBlur
535+
clearOnBlur={clearOnBlur}
527536
{...sanitizeInputRestProps(rest)}
528537
freeSolo={!!create || !!onCreate}
529538
handleHomeEndKeys={!!create || !!onCreate}
@@ -543,7 +552,7 @@ If you provided a React element for the optionText prop, you must also provide t
543552
}
544553
value={selectedChoice}
545554
onChange={handleAutocompleteChange}
546-
onBlur={field.onBlur}
555+
onBlur={finalOnBlur}
547556
onInputChange={handleInputChange}
548557
renderOption={(props, record: RaRecord) => {
549558
(props as {

0 commit comments

Comments
 (0)