<AutocompleteInput>
To let users choose a value in a list using a dropdown with autocompletion, use <AutocompleteInput>
.
It renders using MUI Autocomplete.
Set the choices
attribute to determine the options list (with id
, name
tuples).
import { AutocompleteInput } from 'react-admin';
<AutocompleteInput source="category" choices={[
{ id: 'programming', name: 'Programming' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'photography', name: 'Photography' },
]} />
Properties
Prop | Required | Type | Default | Description |
---|---|---|---|---|
choices |
Required | Object[] |
- |
List of items to autosuggest |
create |
Optional | Element |
- |
A React Element to render when users want to create a new choice |
createItemLabel |
Optional | string |
ra.action.create_item |
The label for the menu item allowing users to create a new choice. Used when the filter is not empty |
emptyValue |
Optional | any |
'' |
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 |
onCreate |
Optional | Function |
- |
A function called with the current filter value when users choose to create a new choice. |
optionText |
Optional | string | Function | Component |
name |
Field name of record to display in the suggestion item or function which accepts the correct record as argument ((record)=> {string} ) |
optionValue |
Optional | string |
id |
Field name of record containing the value to use as input value |
inputText |
Optional | Function |
- |
Required if optionText is a custom Component, this function must return the text displayed for the current selection. |
filterToQuery |
Optional | string => Object |
searchText => ({ q: [searchText] }) |
How to transform the searchText into a parameter for the data provider |
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().length > 2 |
suggestionLimit |
Optional | number |
null |
Limits the numbers of suggestions that are shown in the dropdown list |
<AutocompleteInput>
also accepts the common input props.
Usage
You can customize the properties to use for the option name and value, thanks to the optionText
and optionValue
attributes:
const choices = [
{ _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
{ _id: 456, full_name: 'Jane Austen', sex: 'F' },
];
<AutocompleteInput source="author_id" choices={choices} optionText="full_name" optionValue="_id" />
optionText
also accepts a function, so you can shape the option text at will:
const choices = [
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi' },
{ id: 456, first_name: 'Jane', last_name: 'Austen' },
];
const optionRenderer = choice => `${choice.first_name} ${choice.last_name}`;
<AutocompleteInput source="author_id" choices={choices} optionText={optionRenderer} />
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:
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 => (
<span>
<img src={choice.avatar} />
{choice.first_name} {choice.last_name}
</span>
);
const inputText = choice => `${choice.first_name} ${choice.last_name}`;
const matchSuggestion = (filter, choice) => {
return (
choice.first_name.toLowerCase().includes(filter.toLowerCase())
|| choice.last_name.toLowerCase().includes(filter.toLowerCase())
);
};
<AutocompleteInput
source="author_id"
choices={choices}
optionText={<OptionRenderer />}
inputText={inputText}
matchSuggestion={matchSuggestion}
/>
The choices are translated by default, so you can use translation identifiers as choices:
const choices = [
{ id: 'M', name: 'myroot.gender.male' },
{ id: 'F', name: 'myroot.gender.female' },
];
However, in some cases (e.g. inside a <ReferenceInput>
), you may not want the choice to be translated.
In that case, set the translateChoice
prop to false
.
<AutocompleteInput source="gender" choices={choices} translateChoice={false}/>
When dealing with a large amount of choices
you may need to limit the number of suggestions that are rendered in order to maintain usable performance. The shouldRenderSuggestions
is an optional prop that allows you to set conditions on when to render suggestions. An easy way to improve performance would be to skip rendering until the user has entered 2 or 3 characters in the search box. This lowers the result set significantly, and might be all you need (depending on your data set).
Ex. <AutocompleteInput shouldRenderSuggestions={(val) => { return val.trim().length > 2 }} />
would not render any suggestions until the 3rd character has been entered. This prop is passed to the underlying react-autosuggest
component and is documented here.
<AutocompleteInput>
renders a MUI <Autocomplete>
component and it accepts the <Autocomplete>
props:
<AutocompleteInput source="category" size="large" />
Tip: If you want to populate the choices
attribute with a list of related records, you should decorate <AutocompleteInput>
with <ReferenceInput>
, and leave the choices
empty:
import { AutocompleteInput, ReferenceInput } from 'react-admin';
<ReferenceInput label="Post" source="post_id" reference="posts">
<AutocompleteInput optionText="title" />
</ReferenceInput>
Tip: <AutocompleteInput>
is a stateless component, so it only allows to filter the list of choices, not to extend it. If you need to populate the list of choices based on the result from a fetch
call (and if <ReferenceInput>
doesn’t cover your need), you’ll have to write your own Input component based on MUI <AutoComplete>
component.
Creating New Choices
The <AutocompleteInput>
can allow users to create a new choice if either the create
or onCreate
prop is provided.
Use the onCreate
prop when you only require users to provide a simple string and a prompt
is enough. You can return either the new choice directly or a Promise resolving to the new choice.
import { AutocompleteInput, Create, SimpleForm, TextInput } from 'react-admin';
const PostCreate = () => {
const categories = [
{ name: 'Tech', id: 'tech' },
{ name: 'Lifestyle', id: 'lifestyle' },
];
return (
<Create>
<SimpleForm>
<TextInput source="title" />
<AutocompleteInput
onCreate={(filter) => {
const newCategoryName = window.prompt('Enter a new category', filter);
const newCategory = { id: categories.length + 1, name: newCategoryName };
categories.push(newCategory);
return newCategory;
}}
source="category"
choices={categories}
/>
</SimpleForm>
</Create>
);
}
Use the create
prop when you want a more polished or complex UI. For example a MUI <Dialog>
asking for multiple fields because the choices are from a referenced resource.
import {
AutocompleteInput,
Create,
ReferenceInput,
SimpleForm,
TextInput,
useCreate,
useCreateSuggestionContext
} from 'react-admin';
import {
Box,
BoxProps,
Button,
Dialog,
DialogActions,
DialogContent,
TextField,
} from '@mui/material';
const PostCreate = () => {
return (
<Create>
<SimpleForm>
<TextInput source="title" />
<ReferenceInput source="category_id" reference="categories">
<AutocompleteInput create={<CreateCategory />} />
</ReferenceInput>
</SimpleForm>
</Create>
);
}
const CreateCategory = () => {
const { filter, onCancel, onCreate } = useCreateSuggestionContext();
const [value, setValue] = React.useState(filter || '');
const [create] = useCreate();
const handleSubmit = event => {
event.preventDefault();
create(
'categories',
{
data: {
title: value,
},
},
{
onSuccess: (data) => {
setValue('');
onCreate(data);
},
}
);
};
return (
<Dialog open onClose={onCancel}>
<form onSubmit={handleSubmit}>
<DialogContent>
<TextField
label="New category name"
value={value}
onChange={event => setValue(event.target.value)}
autoFocus
/>
</DialogContent>
<DialogActions>
<Button type="submit">Save</Button>
<Button onClick={onCancel}>Cancel</Button>
</DialogActions>
</form>
</Dialog>
);
};
Tip: As showcased in this example, react-admin provides a convenience hook for accessing the filter the user has already input in the <AutocompleteInput>
: useCreateSuggestionContext
.
The Create %{item}
option will only be displayed once the user has already set a filter (by typing in some input). If you expect your users to create new items often, you can make this more user friendly by adding a placeholder text like this:
const PostCreate = () => {
const categories = [
{ name: 'Tech', id: 'tech' },
{ name: 'Lifestyle', id: 'lifestyle' },
];
return (
<Create>
<SimpleForm>
<TextInput source="title" />
<AutocompleteInput
onCreate={(filter) => {
const newCategoryName = window.prompt('Enter a new category', filter);
const newCategory = { id: categories.length + 1, name: newCategoryName };
categories.push(newCategory);
return newCategory;
}}
source="category"
choices={categories}
+ TextFieldProps={{
+ placeholder: 'Start typing to create a new item',
+ }}
/>
</SimpleForm>
</Create>
);
}
sx
: CSS API
This component doesn’t apply any custom styles on top of MUI <Autocomplete>
component. Refer to their documentation to know its CSS API.