Автозаполнение (Autocomplete)
Автозаполнение - это обычный текстовый ввод, дополненный панелью предлагаемых вариантов.
Виджет полезен для установки значения однострочного текстового поля в одном из двух типов сценариев:
- Значение для текстового поля должно быть выбрано из заранее определенного набора допустимых значений, например, поле местоположения должно содержать допустимое имя местоположения: комбобокс.
- Текстовое поле может содержать любое произвольное значение, но выгодно предложить пользователю возможные значения, например, поле поиска может предложить похожие или предыдущие поиски, чтобы сэкономить время пользователя: свободное соло.
Он должен стать улучшенной версией пакетов "react-select" и "downshift".
Структура опций
По умолчанию компонент принимает следующие структуры опций:
interface AutocompleteOption {
label: string;
}
// or
type AutocompleteOption = string;
например:
const options = [
{ label: 'The Godfather', id: 1 },
{ label: 'Pulp Fiction', id: 2 },
];
// or
const options = ['The Godfather', 'Pulp Fiction'];
Однако вы можете использовать различные структуры, предоставив параметр getOptionLabel
.
Игровая площадка
Каждый из следующих примеров демонстрирует одну из возможностей компонента Autocomplete.
Управляемые состояния
Компонент имеет два состояния, которыми можно управлять:
- состояние "значение" с помощью комбинации свойств
value
/onChange
. Это состояние представляет собой значение, выбранное пользователем, например, при нажатии Enter. - состояние "введенное значение" с помощью комбинации реквизитов
inputValue
/onInputChange
. Это состояние представляет собой значение, отображаемое в текстовом поле.
Свободное соло
Установите freeSolo
в true, чтобы текстовое поле могло содержать любое произвольное значение.
Поле поиска
Этот реквизит предназначен для основного случая использования поискового ввода с предложениями, например, поиск Google или react-autowhatever.
С созданием опций
Если вы планируете использовать этот режим для комбобокса (расширенная версия элемента select), мы рекомендуем установить следующие параметры
selectOnFocus
, чтобы помочь пользователю очистить выбранное значение.clearOnBlur
, чтобы помочь пользователю ввести новое значение.handleHomeEndKeys
для перемещения фокуса внутри всплывающего окна с помощью клавиш Home и End.- Последний вариант, например:
Добавить "ВВЕДЕННОЕ ЗНАЧЕНИЕ"
.
Можно также вывести диалоговое окно, когда пользователь хочет добавить новое значение.
Сгруппированные
Вы можете сгруппировать параметры с помощью атрибута groupBy
.
Если вы это сделаете, убедитесь, что опции также отсортированы по тому же измерению, по которому они сгруппированы,
в противном случае вы увидите дублирующиеся заголовки.
Чтобы управлять отображением групп, предоставьте атрибут renderGroup
.
Это функция, которая принимает объект с двумя полями:
group
- строка, представляющая имя группыchildren
- коллекция элементов списка, которые принадлежат группе.
Следующая демонстрация показывает, как использовать этот атрибут для определения пользовательской разметки и переопределения стилей групп по умолчанию:
useAutocomplete
.
Для расширенной настройки используется headless хук useAutocomplete()
.
Он принимает почти те же параметры, что и компонент Autocomplete, за вычетом всех реквизитов.
связанные с рендерингом JSX.
Компонент Autocomplete построен на этом хуке.
import { useAutocomplete } from '@mui/base/AutocompleteUnstyled';
Хук useAutocomplete
также реэкспортирован из @mui/material для удобства и обратной совместимости.
import useAutocomplete from '@mui/material/useAutocomplete';
Перейдите в раздел Кастомизация для примера с компонентом Autocomplete
вместо хука.
Асинхронные запросы
Компонент поддерживает два различных случая асинхронного использования:
- Загрузка при открытии: он ждет, пока компонент, с которым взаимодействуют, загрузит опции.
- Поиск по мере ввода текста: при каждом нажатии клавиши выполняется новый запрос.
Загрузка при открытии
Он отображает состояние выполнения, пока запрос сети находится на рассмотрении.
Поиск по мере ввода
Если ваша логика заключается в получении новых вариантов при каждом нажатии клавиши и использовании текущего значения текстового поля для фильтрации на сервере, вам стоит подумать о дросселировании запросов.
Кроме того, вам нужно отключить встроенную фильтрацию компонента Autocomplete
путем
переопределив атрибут filterOptions
:
<Autocomplete filterOptions={(x) => x} />
Google Maps
Настроенный интерфейс для автозаполнения мест из Google Maps. Для этого демо нам необходимо загрузить Google Maps JavaScript и Google Places API.
Множественные значения
Также известны как теги, пользователю разрешается вводить более одного значения.
Фиксированные опции
В случае, если вам нужно заблокировать определенные теги, чтобы их нельзя было удалить, вы можете установить отключение фишек.
Ограничение тегов
Вы можете использовать параметр limitTags
, чтобы ограничить количество отображаемых опций, когда они не сфокусированы.
Кастомизация
Выбор элемента для поля ввода
Реквизит renderInput
позволяет вам настраивать отображаемое поле для ввода.
Первый аргумент этого реквизита render содержит реквизиты, которые вам необходимо переслать.
Обратите особое внимание на ключи ref
и inputProps
.
Перейдите в раздел Customized hook для примера настройки с хуком useAutocomplete
вместо компонента.
Выделение
Следующая демонстрация основана на autosuggest-highlight, небольшой (1 кБ) утилите для выделения текста в компонентах autosuggest и autocomplete.
Пользовательский фильтр
Компонент предоставляет фабрику для создания метода фильтра, который может быть предоставлен в свойстве filterOptions
.
Вы можете использовать его для изменения поведения фильтра опций по умолчанию.
import { createFilterOptions } from '@mui/material/Autocomplete';
TODOTRAN доперевести
createFilterOptions(config) => filterOptions
Arguments
config
(object [optional]):
config.ignoreAccents
(bool [optional]): Defaults totrue
. Remove diacritics.config.ignoreCase
(bool [optional]): Defaults totrue
. Lowercase everything.config.limit
(number [optional]): Default to null. Limit the number of suggested options to be shown. For example, ifconfig.limit
is100
, only the first100
matching options are shown. It can be useful if a lot of options match and virtualization wasn't set up.config.matchFrom
('any' | 'start' [optional]): Defaults to'any'
.config.stringify
(func [optional]): Controls how an option is converted into a string so that it can be matched against the input text fragment.config.trim
(bool [optional]): Defaults tofalse
. Remove trailing spaces.
Returns
filterOptions
: the returned filter method can be provided directly to the filterOptions
prop of the Autocomplete
component, or the parameter of the same name for the hook.
In the following demo, the options need to start with the query prefix:
const filterOptions = createFilterOptions({
matchFrom: 'start',
stringify: (option) => option.title,
});
<Autocomplete filterOptions={filterOptions} />;
Advanced
For richer filtering mechanisms, like fuzzy matching, it's recommended to look at match-sorter. For instance:
import { matchSorter } from 'match-sorter';
const filterOptions = (options, { inputValue }) => matchSorter(options, inputValue);
<Autocomplete filterOptions={filterOptions} />;
Virtualization
Search within 10,000 randomly generated options. The list is virtualized thanks to react-window.
Events
If you would like to prevent the default key handler behavior, you can set the event's defaultMuiPrevented
property to true
:
<Autocomplete
onKeyDown={(event) => {
if (event.key === 'Enter') {
// Prevent's default 'Enter' behavior.
event.defaultMuiPrevented = true;
// your handler code
}
}}
/>
Limitations
autocomplete/autofill
Browsers have heuristics to help the user fill in form inputs. However, this can harm the UX of the component.
By default, the component disables the input autocomplete feature (remembering what the user has typed for a given field in a previous session) with the autoComplete="off"
attribute.
Google Chrome does not currently support this attribute setting (Issue 587466).
A possible workaround is to remove the id
to have the component generate a random one.
In addition to remembering past entered values, the browser might also propose autofill suggestions (saved login, address, or payment details). In the event you want the avoid autofill, you can try the following:
Name the input without leaking any information the browser can use. e.g.
id="field1"
instead ofid="country"
. If you leave the id empty, the component uses a random id.Set
autoComplete="new-password"
(some browsers will suggest a strong password for inputs with this attribute setting):<TextField {...params} inputProps={{ ...params.inputProps, autoComplete: 'new-password', }} />
Read the guide on MDN for more details.
iOS VoiceOver
VoiceOver on iOS Safari doesn't support the aria-owns
attribute very well.
You can work around the issue with the disablePortal
prop.
ListboxComponent
If you provide a custom ListboxComponent
prop, you need to make sure that the intended scroll container has the role
attribute set to listbox
. This ensures the correct behavior of the scroll, for example when using the keyboard to navigate.
Accessibility
(WAI-ARIA: https://www.w3.org/WAI/ARIA/apg/patterns/combobox/)
We encourage the usage of a label for the textbox. The component implements the WAI-ARIA authoring practices.