<AutocompleteInput>

To let users choose a value in a list using a dropdown with autocompletion, use <AutocompleteInput>. It renders using MUI Autocomplete.

AutocompleteInput

Set the choices attribute to determine the options list. The value must be an array of objects exposing the id and name for each choice.

import { AutocompleteInput } from 'react-admin';

<AutocompleteInput source="category" choices={[
    { id: 'programming', name: 'Programming' },
    { id: 'lifestyle', name: 'Lifestyle' },
    { id: 'photography', name: 'Photography' },
]} />

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 />
</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.

Properties

Prop Required Type Default Description
choices Optional Object[] - List of items to autosuggest. Required if not inside a ReferenceInput.
create Optional Element - A React Element to render when users want to create a new choice
createLabel Optional string ra.action.create The label for the menu item allowing users to create a new choice. Used when the filter is empty
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
debounce Optional number 250 The delay to wait before calling the setFilter function injected when used in a ReferenceInput.
emptyText Optional string '' The text to use for the empty element
emptyValue Optional any '' The value to use for the empty element
inputText Optional Function - Required if optionText is a custom Component, this function must return the text displayed for the current selection.
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
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 set up 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 MUI Autocomplete 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.

choices

An array of objects that represents the possible suggestions. The objects must have 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: 'programming', name: 'Programming' },
    { id: 'lifestyle', name: 'Lifestyle' },
    { id: 'photography', name: 'Photography' },
];

<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 = [
    { name: 'programming', label: 'Programming' },
    { name: 'lifestyle', label: 'Lifestyle' },
    { name: 'photography', label: 'Photography' },
];

<AutocompleteInput
    source="category"
    optionValue="name"
    optionText="label"
    choices={choices}
/>

When used inside a <ReferenceInput>, <AutocompleteInput> doesn’t need a choices prop. Instead, it will use the records fetched by <ReferenceInput> as choices, via the ChoicesContext.

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

See Using in a ReferenceInput> below for more information.

emptyText

If the input isn’t required (using validate={required()}), users can select an empty choice with an empty text '' as label.

You can override that label with the emptyText prop.

<AutocompleteInput
    source="author_id"
    emptyText="No author"
    choices={[
        { id: 123, name: 'Leo Tolstoi' },
        { id: 456, name: 'Jane Austen' },
    ]}
/>

The emptyText prop accepts either a string or a React Element.

And if you want to hide that empty choice, make the input required.

<AutocompleteInput
    source="author_id"
    choices={[
        { id: 123, name: 'Leo Tolstoi' },
        { id: 456, name: 'Jane Austen' },
    ]}
    validate={required()}
/>

emptyValue

If the input isn’t required (using validate={required()}), users can select an empty choice. The default value for that empty choice is the empty string (''), or null if the input is inside a <ReferenceInput>.

You can override this value with the emptyValue prop.

<AutocompleteInput
    source="author_id"
    emptyValue={0}
    emptyText="No author"
    choices={[
        { id: 123, name: 'Leo Tolstoi' },
        { id: 456, name: 'Jane Austen' },
    ]}
/>

Tip: While you can set emptyValue to a non-string value (e.g. 0), you cannot use null or undefined, as it would turn the <AutocompleteInput> into an uncontrolled component. If you need the empty choice to be stored as null or undefined, use the parse prop to convert the default empty value (‘’) to null or undefined, or use the sanitizeEmptyValues prop on the Form component.

optionText

You can customize the choice field to use for the option name, thanks to the optionText attribute:

// no 'name' field in the choices
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" />

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 a 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}
/>

optionValue

You can customize the choice field to use for the option value, thanks to the optionValue attribute:

// no 'id' field in the choices
const choices = [
    { _id: 123, name: 'Leo Tolstoi' },
    { _id: 456, name: 'Jane Austen' },
];
<AutocompleteInput source="author_id" choices={choices} optionValue="_id" />

translateChoice

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}/>

shouldRenderSuggestions

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.

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.

Additional Props

<AutocompleteInput> renders a MUI <Autocomplete> component and it accepts the <Autocomplete> props:

<AutocompleteInput source="category" size="large" />

Using In A ReferenceInput

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="Author" source="author_id" reference="authors">
    <AutocompleteInput />
</ReferenceInput>

In that case, <AutocompleteInput> uses the recordRepresentation to render each choice from the list of possible records. You can override this behavior by setting the optionText prop:

import { AutocompleteInput, ReferenceInput } from 'react-admin';

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

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 an 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 convenient 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>
    );
}