Skip to content

AutocompleteInput

Form control that tets users choose a value in a list using a dropdown with autocompletion. This input allows editing record fields that are scalar values, e.g. 123, 'admin', etc.

In addition to the source, <AutocompleteInput> requires one prop: the choices listing the possible values.

import { AutocompleteInput } from '@/components/admin';
<AutocompleteInput source="category" choices={[
{ id: 'tech', name: 'Tech' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'people', name: 'People' },
]} />

By default, the possible choices are built from the choices prop, using:

  • the id field as the option value,
  • the name field as the option text

The form value for the source must be the selected value, e.g.

{
id: 123,
title: 'Lorem Ipsum',
category: 'lifestyle',
}
PropRequiredTypeDefaultDescription
sourceRequired*string-Field name (inferred in ReferenceInput)
choicesRequired*Object[]-List of items to autosuggest. Required if not inside a ReferenceInput.
classNameOptionalstring-The class name to apply to the root element
createOptionalElement-A React Element to render when users want to create a new choice
createItemLabelOptionalstring | (filter: string) => ReactNodera.action .create_itemThe label for the menu item allowing users to create a new choice. Used when the filter is not empty.
createLabelOptionalstring | ReactNode-The label used as hint to let users know they can create a new choice. Displayed when the filter is empty.
debounceOptionalnumber250The delay to wait before calling the setFilter function injected when used in a ReferenceInput.
defaultValueOptionalany''The default value for the input
disabledOptionalbooleanfalseIf true, the input is disabled
emptyTextOptionalstring''The text to use for the empty element
emptyValueOptionalany''The value to use for the empty element
filterToQueryOptionalstring => Objectq => ({ q })How to transform the searchText into a parameter for the data provider
formatOptionalFunction-Callback taking the value from the form state, and returning the input value.
helperTextOptionalstring | ReactNode-The helper text to display below the input
inputTextOptionalFunction-Required if optionText is a custom Component, this function must return the text displayed for the current selection.
isPendingOptionalbooleanfalseIf true, the component will display a loading indicator.
labelOptionalstring | ReactNode-The label to display for the input
matchSuggestionOptionalFunction-Required if optionText is a React element. Function returning a boolean indicating whether a choice matches the filter. (filter, choice) => boolean
offlineOptionalReactNode-What to render when there is no network connectivity when fetching the choices
onChangeOptionalFunction-A function called with the new value, along with the selected record, when the input value changes
onCreateOptionalFunction-A function called with the current filter value when users choose to create a new choice.
optionTextOptionalstring | Function | Componentundefined | record RepresentationField name of record to display in the suggestion item or function using the choice object as argument
optionValueOptionalstringidField name of record containing the value to use as input value
parseOptionalFunction-Callback taking the value from the input, and returning the value to be stored in the form state.
setFilterOptionalFunctionnullA callback to inform the searchText has changed and new choices can be retrieved based on this searchText. Signature searchText => void. This function is automatically set up when using ReferenceInput.
shouldRenderSuggestionsOptionalFunction() => trueA function that returns a boolean to determine whether or not suggestions are rendered.
suggestionLimitOptionalnumbernullLimits the numbers of suggestions that are shown in the dropdown list
translateChoiceOptionalbooleantrueWhether the choices should be translated
validateOptionalFunction | Function[]-An array of validation functions or a single validation function

* source and choices are optional inside <ReferenceInput>.

The list of choices must be an array of objects with at least two fields: one to use for the name, and the other to use for the value. By default, <AutocompleteInput> will use the id and name fields.

const choices = [
{ id: 'tech', name: 'Tech' },
{ id: 'lifestyle', name: 'Lifestyle' },
{ id: 'people', name: 'People' },
];
<AutocompleteInput source="category" choices={choices} />

If the choices have different keys, you can use optionText and optionValue to specify which fields to use for the name and value.

const choices = [
{ _id: 'tech', label: 'Tech' },
{ _id: 'lifestyle', label: 'Lifestyle' },
{ _id: 'people', label: 'People' },
];
<AutocompleteInput
source="category"
choices={choices}
optionText="label"
optionValue="_id"
/>

The choices are translated by default, so you can use translation identifiers as choices:

const choices = [
{ id: 'tech', name: 'myroot.categories.tech' },
{ id: 'lifestyle', name: 'myroot.categories.lifestyle' },
{ id: 'people', name: 'myroot.categories.people' },
];

You can opt-out of this translation by setting the translateChoice prop to false.

If you need to fetch the options from another resource, you’re usually editing a many-to-one or a one-to-one relationship. In this case, wrap the <AutocompleteInput> in a <ReferenceInput>. You don’t need to specify the source and choices prop in this case - the parent component injects them based on the possible values of the related resource.

<ReferenceInput label="Author" source="author_id" reference="authors">
<AutocompleteInput />
</ReferenceInput>

You can also pass an array of strings for the choices:

const categories = ['tech', 'lifestyle', 'people'];
<AutocompleteInput source="category" choices={categories} />
// is equivalent to
const choices = categories.map(value => ({ id: value, name: value }));
<AutocompleteInput source="category" choices={choices} />

When used inside a <ReferenceInput>, whenever users type a string in the autocomplete input, <AutocompleteInput> calls dataProvider.getList() using the string as filter, to return a filtered list of possible options from the reference resource. This filter is built using the filterToQuery prop.

By default, the filter is built using the q parameter. This means that if the user types the string ‘lorem’, the filter will be { q: 'lorem' }.

You can customize the filter by setting the filterToQuery prop. It should be a function that returns a filter object.

const filterToQuery = searchText => ({ name_ilike: `%${searchText}%` });
<ReferenceInput label="Author" source="author_id" reference="authors">
<AutocompleteInput filterToQuery={filterToQuery} />
</ReferenceInput>

You can pass a custom element as optionText to have <AutocompleteInput> render each suggestion in a custom way.

<AutocompleteInput> will render the custom option element inside a <RecordContext>, using the related choice as the record prop. You can use Field components there.

However, as the underlying Material UI <Autocomplete> component requires that the current selection is a string, you must also pass a function as the inputText prop. This function should return a text representation of the current selection. You should also pass a matchSuggestion function to filter the choices based on the current selection.

const choices = [
{ id: 123, first_name: 'Leo', last_name: 'Tolstoi', avatar:'/penguin' },
{ id: 456, first_name: 'Jane', last_name: 'Austen', avatar:'/panda' },
];
const OptionRenderer = () => {
const record = useRecordContext();
return (
<span>
<img src={record.avatar} />
{record.first_name} {record.last_name}
</span>
);
};
const optionText = <OptionRenderer />;
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={optionText}
inputText={inputText}
matchSuggestion={matchSuggestion}
/>

To allow users to add new options, pass a React element as the create prop. <AutocompleteInput> will then render a menu item at the bottom of the list, which will render the passed element when clicked.

import {
Create,
CreateBase,
SimpleForm,
ReferenceInput,
AutocompleteInput,
TextInput,
useCreateSuggestionContext
} from 'react-admin';
const CreateTag = () => {
const { onCancel, onCreate, filter } = useCreateSuggestionContext();
const [newTagName, setNewTagName] = React.useState(filter ?? "");
const handleChangeTagName = (event: React.ChangeEvent<HTMLInputElement>) => {
setNewTagName(event.currentTarget.value);
};
const saveTag = () => {
const newTag = { label: newTagName, id: newTagName.toLowerCase() };
tags.push(newTag);
setNewTagName("");
onCreate(newTag);
};
const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
saveTag();
};
return (
<Dialog open onOpenChange={onCancel}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Create a tag</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">New tag name</Label>
<Input id="name" value={newTagName} onChange={handleChangeTagName} autoFocus />
</div>
</form>
<DialogFooter>
<Button variant="outline" onClick={onCancel}>Cancel</Button>
<Button onClick={saveTag}>Save</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
const BookCreateEdit = () => (
<Edit>
<SimpleForm>
<AutocompleteInput
source="tag_id"
choices={tags}
optionText="label"
create={<CreateTag />}
createLabel="Start typing to create a new tag"
createItemLabel="Create %{item}"
/>
</SimpleForm>
</Edit>
);

If you want to customize the label of the “Create XXX” option, use the createItemLabel prop.

If you just need to ask users for a single string to create the new option, you can use the onCreate prop instead.