Skip to content

Fix AutocompleteInput suggestions flicker when used inside ReferenceInput #8037

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 5, 2022
86 changes: 82 additions & 4 deletions docs/AutocompleteInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,59 @@ import { AutocompleteInput, ReferenceInput } from 'react-admin';

`<AutocompleteInput>` also accepts the [common input props](./Inputs.md#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.

```jsx
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`](#optiontext) and [`optionValue`](#optionvalue) to specify which fields to use for the name and value.

```jsx
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`.

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

See [Using in a `ReferenceInput>`](#using-in-a-referenceinput) below for more information.


## `optionText`

You can customize the properties to use for the option name and value, thanks to the `optionText` and `optionValue` attributes:
You can customize the choice field to use for the option name, thanks to the `optionText` attribute:

```jsx
// no 'name' field in the choices
const choices = [
{ _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
{ _id: 456, full_name: 'Jane Austen', sex: 'F' },
{ 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" />
<AutocompleteInput source="author_id" choices={choices} optionText="full_name" />
```

`optionText` also accepts a function, so you can shape the option text at will:
Expand Down Expand Up @@ -108,6 +151,19 @@ const matchSuggestion = (filter, choice) => {
/>
```

## `optionValue`

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

```jsx
// 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:
Expand Down Expand Up @@ -145,6 +201,28 @@ This component doesn't apply any custom styles on top of [MUI `<Autocomplete>` c
```
{% endraw %}

## Using In A ReferenceInput

If you want to populate the `choices` attribute with a list of related records, you should decorate `<AutocompleteInput>` with [`<ReferenceInput>`](./ReferenceInput.md), and leave the `choices` empty:

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

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

In that case, `<AutocompleteInput>` uses the [`recordRepresentation`](./Resource.md#recordrepresentation) to render each choice from the list of possible records. You can override this behavior by setting the `optionText` prop:

```jsx
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.
Expand Down
22 changes: 18 additions & 4 deletions docs/SelectInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,15 @@ Refer to [MUI Select documentation](https://mui.com/api/select) for more details

## `optionText`

You can customize the properties to use for the option name and value, thanks to the `optionText` and `optionValue` attributes:
You can customize the choice field to use for the option name, thanks to the `optionText` attribute:

```jsx
// no 'name' field in the choices
const choices = [
{ _id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
{ _id: 456, full_name: 'Jane Austen', sex: 'F' },
{ id: 123, full_name: 'Leo Tolstoi', sex: 'M' },
{ id: 456, full_name: 'Jane Austen', sex: 'F' },
];
<SelectInput source="author_id" choices={choices} optionText="full_name" optionValue="_id" />
<SelectInput source="author_id" choices={choices} optionText="full_name" />
```

`optionText` also accepts a function, so you can shape the option text at will:
Expand All @@ -158,6 +159,19 @@ const FullNameField = ({ record }) => <span>{record.first_name} {record.last_nam
<SelectInput source="gender" choices={choices} optionText={<FullNameField />}/>
```

## `optionValue`

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

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

## `resettable`

You can make the `SelectInput` component resettable using the `resettable` prop. This will add a reset button which will be displayed only when the field has a value.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const useReferenceInputController = <RecordType extends RaRecord = any>(
},
{
enabled: isGetMatchingEnabled,
keepPreviousData: true,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the main cause of the flicker

...queryOptions,
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,13 @@ const BookEditWithReference = () => (
>
<SimpleForm>
<ReferenceArrayInput reference="authors" source="author">
<AutocompleteArrayInput fullWidth />
<AutocompleteArrayInput fullWidth optionText="name" />
</ReferenceArrayInput>
</SimpleForm>
</Edit>
);

export const InsideReferenceInput = () => (
export const InsideReferenceArrayInput = () => (
<Admin dataProvider={dataProviderWithAuthors} history={history}>
<Resource name="authors" />
<Resource name="books" edit={BookEditWithReference} />
Expand Down Expand Up @@ -400,13 +400,17 @@ const BookEditWithReferenceAndCreationSupport = () => (
>
<SimpleForm>
<ReferenceArrayInput reference="authors" source="author">
<AutocompleteArrayInput create={<CreateAuthor />} fullWidth />
<AutocompleteArrayInput
create={<CreateAuthor />}
fullWidth
optionText="name"
/>
</ReferenceArrayInput>
</SimpleForm>
</Edit>
);

export const InsideReferenceInputWithCreationSupport = () => (
export const InsideReferenceArrayInputWithCreationSupport = () => (
<Admin dataProvider={dataProviderWithAuthors} history={history}>
<Resource name="authors" />
<Resource name="books" edit={BookEditWithReferenceAndCreationSupport} />
Expand Down
Loading