Saltar al contenido

Autocompletado

El autocompletado es una caja de texto normal mejorada por un panel de opciones sugeridas.

El widget es útil para establecer el valor de un cuadro de texto de una sola línea en uno de los dos tipos de escenarios:

  1. El valor para el cuadro de texto debe elegirse de un conjunto predefinido de valores permitidos, por ejemplo, un campo de ubicación debe contener un nombre de ubicación válido: cuadro combinado.
  2. El cuadro de texto puede contener cualquier valor arbitrario, pero es ventajoso sugerir posibles valores al usuario, por ejemplo, un campo de búsqueda puede sugerir búsquedas similares o anteriores para ahorrarle tiempo al usuario: gratis solo.

It's meant to be an improved version of the "react-select" and "downshift" packages.

Combo box

El valor debe elegirse de un conjunto predefinido de valores permitidos.

<Autocomplete
  id="combo-box-demo"
  options={top100Films}
  getOptionLabel={(option) => option.title}
  style={{ width: 300 }}
  renderInput={(params) => <TextField {...params} label="Combo box" variant="outlined" />}
/>

Playground

Cada uno de los siguientes ejemplos demuestran una característica del componente Autocompletado.

Selección de País

Choose one of the 248 countries.

Controllable states

The component has two states that can be controlled:

  1. the "value" state with the value/onChange props combination.
  2. the "input value" state with the inputValue/onInputChange props combination.

⚠️ These two state are isolated, they should be controlled independently.

Free solo

Setear freeSolo a true, para que el cuadro de texto pueda contener cualquier valor arbitrario. La propiedad está diseñada para cubrir el principal caso de uso de una caja de búsqueda con sugerencias, ej: Google Search.

However, if you intend to use it for a combo box like experience (an enhanced version of a select element) we recommend setting selectOnFocus (it helps the user clear the selected value).

Helper message

Sometimes you want to make explicit to the user that he/she can add whatever value he/she wants. The following demo adds a last option: Add "YOUR SEARCH".

You could also display a dialog when the user wants to add a new value.

Grouped

<Autocomplete
  id="grouped-demo"
  options={options.sort((a, b) => -b.firstLetter.localeCompare(a.firstLetter))}
  groupBy={(option) => option.firstLetter}
  getOptionLabel={(option) => option.title}
  style={{ width: 300 }}
  renderInput={(params) => <TextField {...params} label="With categories" variant="outlined" />}
/>

Disabled options

<Autocomplete
  id="disabled-options-demo"
  options={timeSlots}
  getOptionDisabled={(option) => option === timeSlots[0] || option === timeSlots[2]}
  style={{ width: 300 }}
  renderInput={(params) => (
    <TextField {...params} label="Disabled options" variant="outlined" />
  )}
/>

useAutocomplete

For advanced customization use cases, we expose a useAutocomplete() hook. It accepts almost the same options as the Autocomplete component minus all the props related to the rendering of JSX. The Autocomplete component uses this hook internally.

import useAutocomplete from '@material-ui/lab/useAutocomplete';

Customized hook

Head to the Customized Autocomplete section for a customization example with the Autocomplete component instead of the hook.

Asynchronous requests

Google Maps place

A customized UI for Google Maps Places Autocomplete.

For this demo, we need to load the Google Maps JavaScript API.

⚠️ Before you can start using the Google Maps JavaScript API, you must sign up and create a billing account.

Multiple values

Also known as tags, the user is allowed to enter more than one value.

Fixed options

In the event that you need to lock certain tag so that they can't be removed in the interface, you can set the chips disabled.

<Autocomplete
  multiple
  id="fixed-tags-demo"
  options={top100Films}
  getOptionLabel={(option) => option.title}
  defaultValue={[top100Films[6], top100Films[13]]}
  renderTags={(value, getTagProps) =>
    value.map((option, index) => (
      <Chip label={option.title} {...getTagProps({ index })} disabled={index === 0} />
    ))
  }
  style={{ width: 500 }}
  renderInput={(params) => (
    <TextField {...params} label="Fixed tag" variant="outlined" placeholder="Favorites" />
  )}
/>

Casillas de Verificación

Limit tags

You can use the limitTags prop to limit the number of displayed options when not focused.

<Autocomplete
  multiple
  limitTags={2}
  id="multiple-limit-tags"
  options={top100Films}
  getOptionLabel={(option) => option.title}
  defaultValue={[top100Films[13], top100Films[12], top100Films[11]]}
  renderInput={(params) => (
    <TextField {...params} variant="outlined" label="limitTags" placeholder="Favorites" />
  )}
/>

Tamaños

Fancy smaller inputs? Use the size prop.

Autocompletado personalizado

This demo reproduces the GitHub's label picker:

help wanted
type: bug

Head to the Customized hook section for a customization example with the useAutocomplete hook instead of the component.

Destacados

La siguiente demostración se basa en autosuggest-highlight, una pequeña utilidad (1 kB) para resaltar texto en componentes de autosuggest y autocompletar.

Filtro personalizado

The component exposes a factory to create a filter method that can provided to the filerOption prop. You can use it to change the default option filter behavior.

import { createFilterOptions } from '@material-ui/lab/Autocomplete';

createFilterOptions(config) => filterOptions

Argumentos

  1. config (Object [optional]):
    • config.ignoreAccents (Boolean [optional]): Defaults to true. Remove diacritics.
    • config.ignoreCase (Boolean [optional]): Defaults to true. Lowercase everything.
    • config.limit (Number [optional]): Default to null. Limit the number of suggested options to be shown. For example, if config.limit is 100, only the first 100 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.startAfter(Number [optional]): Default to 0. Show the suggested options only after a certain number of letters
    • 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 (Boolean [optional]): Default false. Remove trailing spaces.

Regresa

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

Avanzado

For richer filtering mechanisms, like fuzzy matching, it's recommended to look at match-sorter. Por ejemplo:

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.

<Autocomplete
  id="virtualize-demo"
  style={{ width: 300 }}
  disableListWrap
  classes={classes}
  ListboxComponent={ListboxComponent}
  renderGroup={renderGroup}
  options={OPTIONS}
  groupBy={(option) => option[0].toUpperCase()}
  renderInput={(params) => <TextField {...params} variant="outlined" label="10,000 options" />}
  renderOption={(option) => <Typography noWrap>{option}</Typography>}
/>

Limitaciones

autocomplete/autofill

The browsers have heuristics to help the users fill the form inputs. However, it can harm the UX of the component.

By default, the component disable the autocomplete feature (remembering what the user has typed for a given field in a previous session) with the autoComplete="off" attribute.

However, 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 of id="country". If you leave the id empty, the component uses a random id.
  • Set autoComplete="new-password":
      jsx
      <TextField
      {...params}
      inputProps={{
        ...params.inputProps,
        autoComplete: 'new-password',
      }}
      />

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.

TypeScript

To fully take advantage of type inference, you need to set the multiple prop to undefined, false or true. See this discussion for more details. TypeScript might solve this bug in the future.

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.

Accesibilidad

(WAI-ARIA: https://www.w3.org/TR/wai-aria-practices/#combobox)

We encourage the usage of a label for the textbox. The component implements the WAI-ARIA authoring practices.