diff --git a/packages/ra-ui-materialui/src/input/AutocompleteInput.spec.tsx b/packages/ra-ui-materialui/src/input/AutocompleteInput.spec.tsx
index e66e6f0a924..f8f746b43b1 100644
--- a/packages/ra-ui-materialui/src/input/AutocompleteInput.spec.tsx
+++ b/packages/ra-ui-materialui/src/input/AutocompleteInput.spec.tsx
@@ -17,6 +17,7 @@ import {
DifferentShapeInGetMany,
InsideReferenceInput,
InsideReferenceInputDefaultValue,
+ InsideReferenceInputWithCustomizedItemRendering,
Nullable,
NullishValuesSupport,
VeryLargeOptionsNumber,
@@ -1393,6 +1394,39 @@ describe('', () => {
expect(testFailed).toBe(false);
expect(input.value).toBe('Leo Tolstoy test');
});
+
+ it('should not use getSuggestions to do client-side filtering', async () => {
+ // filtering should be done server-side only, and hence matchSuggestion should never be called
+ const matchSuggestion = jest.fn().mockReturnValue(true);
+ render(
+
+ );
+ await waitFor(
+ () => {
+ expect(
+ (screen.getByRole('textbox') as HTMLInputElement).value
+ ).toBe('Leo Tolstoy - Russian');
+ },
+ { timeout: 2000 }
+ );
+ screen.getByRole('textbox').focus();
+ fireEvent.click(screen.getByLabelText('Clear value'));
+ await waitFor(() => {
+ expect(screen.getByRole('listbox').children).toHaveLength(5);
+ });
+ fireEvent.change(screen.getByRole('textbox'), {
+ target: { value: 'French' },
+ });
+ await waitFor(
+ () => {
+ screen.getByText('No options');
+ },
+ { timeout: 2000 }
+ );
+ expect(matchSuggestion).not.toHaveBeenCalled();
+ });
});
it("should allow to edit the input if it's inside a FormDataConsumer", () => {
diff --git a/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx b/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx
index e9597c06e5c..14e59c28507 100644
--- a/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx
+++ b/packages/ra-ui-materialui/src/input/AutocompleteInput.stories.tsx
@@ -24,7 +24,7 @@ import fakeRestProvider from 'ra-data-fakerest';
import { Edit } from '../detail';
import { SimpleForm } from '../form';
-import { AutocompleteInput } from './AutocompleteInput';
+import { AutocompleteInput, AutocompleteInputProps } from './AutocompleteInput';
import { ReferenceInput } from './ReferenceInput';
import { TextInput } from './TextInput';
import { useCreateSuggestionContext } from './useSupportCreateSuggestion';
@@ -689,6 +689,46 @@ export const InsideReferenceInputWithCreationSupport = () => (
);
+const BookOptionText = () => {
+ const book = useRecordContext();
+ if (!book) return null;
+ return
{`${book.name} - ${book.language}`}
;
+};
+
+export const InsideReferenceInputWithCustomizedItemRendering = (
+ props: Partial
+) => (
+
+
+ (
+ {
+ console.log(data);
+ },
+ }}
+ >
+
+
+ }
+ inputText={book =>
+ `${book.name} - ${book.language}`
+ }
+ {...props}
+ />
+
+
+
+ )}
+ />
+
+);
+
const OptionItem = props => {
const record = useRecordContext();
return (
diff --git a/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx b/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx
index fd891c49ebb..cc919e1e872 100644
--- a/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx
+++ b/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx
@@ -276,8 +276,12 @@ export const AutocompleteInput = <
throw new Error(`
If you provided a React element for the optionText prop, you must also provide the inputText prop (used for the text input)`);
}
- // eslint-disable-next-line eqeqeq
- if (isValidElement(optionText) && matchSuggestion == undefined) {
+ if (
+ isValidElement(optionText) &&
+ !isFromReference &&
+ // eslint-disable-next-line eqeqeq
+ matchSuggestion == undefined
+ ) {
throw new Error(`
If you provided a React element for the optionText prop, you must also provide the matchSuggestion prop (used to match the user input with a choice)`);
}
@@ -515,7 +519,7 @@ If you provided a React element for the optionText prop, you must also provide t
const oneSecondHasPassed = useTimeout(1000, filterValue);
const suggestions = useMemo(() => {
- if (matchSuggestion || limitChoicesToValue) {
+ if (!isFromReference && (matchSuggestion || limitChoicesToValue)) {
return getSuggestions(filterValue);
}
return finalChoices?.slice(0, suggestionLimit) || [];
@@ -526,6 +530,7 @@ If you provided a React element for the optionText prop, you must also provide t
limitChoicesToValue,
matchSuggestion,
suggestionLimit,
+ isFromReference,
]);
const isOptionEqualToValue = (option, value) => {