diff --git a/docs/Inputs.md b/docs/Inputs.md
index 47a5c33ac6d..3c6e1faa655 100644
--- a/docs/Inputs.md
+++ b/docs/Inputs.md
@@ -162,6 +162,28 @@ const optionRenderer = choice => `${choice.first_name} ${choice.last_name}`;
```
+`optionText` also accepts a custom Component. However, as the underlying Autocomplete component requires that the current selection is a string, if you opt for a Component, you must pass a function as the `inputText` prop. This function should return text representation of the current selection:
+
+```jsx
+const choices = [
+ { id: 123, first_name: 'Leo', last_name: 'Tolstoi' avatar='/pengouin' },
+ { id: 456, first_name: 'Jane', last_name: 'Austen' avatar='/panda' },
+];
+const OptionRenderer = choice => (
+
+
+ {choice.first_name} {choice.last_name}
+
+);
+const inputText = choice => `${choice.first_name} ${choice.last_name}`;
+}
+ inputText={inputText}
+/>
+```
+
The choices are translated by default, so you can use translation identifiers as choices:
```jsx
@@ -225,8 +247,9 @@ Lastly, would you need to override the props of the suggestions container (a `Po
| `emptyValue` | Optional | anything | `''` | The value to use for the empty element |
| `emptyText` | Optional | `string` | `''` | The text to use for the empty element |
| `matchSuggestion` | Optional | `Function` | - | Required if `optionText` is a React element. Function returning a boolean indicating whether a choice matches the filter. `(filter, choice) => boolean`
-| `optionText` | Optional | string | Function
| `name` | Fieldname of record to display in the suggestion item or function which accepts the correct record as argument (`(record)=> {string}`) |
+| `optionText` | Optional | string | Function | Component
| `name` | Fieldname of record to display in the suggestion item or function which accepts the correct record as argument (`(record)=> {string}`) |
| `optionValue` | Optional | `string` | `id` | Fieldname of record containing the value to use as input value |
+| `inputText` | Optional | Function
| `-` | If `optionText` is a custom Component, this function is needed to determine the text displayed for the current selection. |
| `setFilter` | Optional | `Function` | `null` | A callback to inform the `searchText` has changed and new `choices` can be retrieved based on this `searchText`. Signature `searchText => void`. This function is automatically setup when using `ReferenceInput`. |
| `shouldRenderSuggestions` | Optional | Function | `() => true` | A function that returns a `boolean` to determine whether or not suggestions are rendered. Use this when working with large collections of data to improve performance and user experience. This function is passed into the underlying react-autosuggest component. Ex.`(value) => value.trim() > 2` |
diff --git a/examples/simple/src/comments/CommentEdit.js b/examples/simple/src/comments/CommentEdit.js
index ce31cdd9082..0ecba92dfd7 100644
--- a/examples/simple/src/comments/CommentEdit.js
+++ b/examples/simple/src/comments/CommentEdit.js
@@ -33,6 +33,14 @@ const useEditStyles = makeStyles({
},
});
+const OptionRenderer = ({ record }) => (
+
+ {record.title} - {record.id}
+
+);
+
+const inputText = record => `${record.title} - ${record.id}`;
+
const CommentEdit = props => {
const classes = useEditStyles();
const {
@@ -74,10 +82,15 @@ const CommentEdit = props => {
fullWidth
>
+ true
+ }
+ optionText={}
+ inputText={inputText}
options={{ fullWidth: true }}
/>
+
', () => {
}
+ inputText={record => record.name}
matchSuggestion={(filter, choice) => true}
choices={[
{ id: 1, name: 'bar' },
diff --git a/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx b/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx
index 4e3aa86e085..84fb2aa934a 100644
--- a/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx
+++ b/packages/ra-ui-materialui/src/input/AutocompleteInput.tsx
@@ -124,6 +124,7 @@ const AutocompleteInput: FunctionComponent<
InputProps: undefined,
},
optionText = 'name',
+ inputText,
optionValue = 'id',
parse,
resource,
@@ -136,6 +137,13 @@ const AutocompleteInput: FunctionComponent<
variant = 'filled',
...rest
}) => {
+ if (isValidElement(optionText) && !inputText) {
+ throw new Error(`If the optionText prop is a React element, you must also specify the inputText prop:
+ record.title}
+ />`);
+ }
+
warning(
isValidElement(optionText) && !matchSuggestion,
`If the optionText prop is a React element, you must also specify the matchSuggestion prop:
@@ -219,8 +227,20 @@ const AutocompleteInput: FunctionComponent<
// If we have a value, set the filter to its text so that
// Downshift displays it correctly
- setFilterValue(input.value ? getChoiceText(selectedItem) : '');
- }, [input.value, handleFilterChange, selectedItem, getChoiceText]);
+ setFilterValue(
+ input.value
+ ? inputText
+ ? inputText(getChoiceText(selectedItem).props.record)
+ : getChoiceText(selectedItem)
+ : ''
+ );
+ }, [
+ input.value,
+ handleFilterChange,
+ selectedItem,
+ getChoiceText,
+ inputText,
+ ]);
const handleChange = useCallback(
(item: any) => {
@@ -267,10 +287,16 @@ const AutocompleteInput: FunctionComponent<
handleFilterChange('');
// If we had a value before, set the filter back to its text so that
// Downshift displays it correctly
- setFilterValue(input.value ? getChoiceText(selectedItem) : '');
+ setFilterValue(
+ input.value
+ ? inputText
+ ? inputText(getChoiceText(selectedItem).props.record)
+ : getChoiceText(selectedItem)
+ : ''
+ );
input.onBlur(event);
},
- [getChoiceText, handleFilterChange, input, selectedItem]
+ [getChoiceText, handleFilterChange, input, inputText, selectedItem]
);
const handleFocus = useCallback(