Type to generate UI components from text

OR

Browse thousands of MUI, Tailwind, React components that are fully customizable and responsive.

Explore Components

How to Supercharge MUI Forms with Autocomplete

When using Google Search, one would notice something about how the search input bar works. The search bar actively predicts what you want to search and displays these predictions as options you can pick from. This helpful behavior is called autocomplete, and it can be found in many places on the internet.

Google Search Home Page

A React Library that allows developers to implement this behavior in their Web Applications easily is Material UI (MUI). Material UI is a popular React Component Library that can handle most User Interface needs of a React Project. It offers components such as Cards, Modals, and Buttons.

This article aims to introduce the Material UI Autocomplete component. It is going to explain the problems an autocomplete feature solves, how to import the MUI Autocomplete component in a project, different Autocomplete Modes, some important props the MUI component has, how to load Autocomplete options asynchronously, best practices for using MUI autocomplete, and more.

But before we learn all of that, are you aware of the developer tool named PureCode? PureCode is a Web Application that helps developers generate custom UI components with AI. It saves developers time, and it also contains thousands of customizable components that fit every type of need. Visit the PureCode Website now to check out the tool.

Prerequisites

To fully understand the content of this article, there are some prerequisites you need to have. These prerequisites are:

  1. Knowledge of HTML

  2. Knowledge of CSS

  3. Knowledge of JavaScript

  4. Basic Knowledge of React.js

Armed with this knowledge, understanding how to use the MUI Autocomplete component is easier and more intuitive.

Why is the Autocomplete feature useful?

Autocomplete is a useful feature of Web Browsers, Search Engines, code editors, and other software. As mentioned earlier, this feature predicts what the user wants to enter as an input value. But why is this feature so useful, and what benefits does it offer? This section of the article lists some of those benefits.

  • Speed: The autocomplete behavior greatly increases the speed with which users get work done in the Application. Because it predicts what the user wants to input, the user might pick one of those options, therefore saving time.

  • Improved User Interface: Having an Autocomplete feature improves a User Interface. It is intuitive to use and guides the user better.

  • Reduced Cognitive Load: Cognitive Load refers to the amount of information in our working memory at a given time. With Autocomplete behavior, the cognitive load is reduced drastically as one can simply pick from the predictions presented rather than actively trying to type out all the words in their intended input value. The autocomplete behavior is also helpful when the words are hard to spell.

  • Enhanced Accessibility: The Autocomplete behavior improves accessibility, especially for users with a disability that makes them not able to type for long. This is obviously essential to the experience of the users within the application.

How to use the MUI Autocomplete

This section is a step-by-step guide on how to import Autocomplete into a React Application. The steps to take are laid out below:

  1. Set up a React Application: Make sure you have a React App running. Here’s a guide on running React with Vite.

  2. Install Material UI: Add Material UI to the React App. This guide details how you can do that.

  3. Import the Autocomplete component: The next step is to import the component in the file you need it. Here is a code sample importing the Autocomplete component.

    import { Autocomplete } from "@mui/material";
  4. Import a Text Input: Autocomplete works with a Text Input. Import the `TextField` component for this.

    import { Autocomplete, TextField } from "@mui/material";
  5. Use the Component: There are two required props to use the Autocomplete component. They are the `options` prop and `renderInput` prop. Here is a simple illustration of those props in use:

    import React from "react";
    impott { Autocomplete, TextField } from "@mui/material";
    
    const nigerianSoups = [
      "Egusi Soup",
      "Ogbono Soup",
      "Afang Soup",
      "Efo riro",
      "Banga Soup",
      "Bitterleaf Soup",
      "Pepper Soup",
      "Okra Soup",
      "Ewedu Soup",
      "Uha Soup",
      "Black Soup",
      "Edikaikong Soup",
      "Miyan Kuka",
      "Ofe Nsala",
      "Ofe Ukazi",
    ];
    
    function App() {
      return (
        <div className="demo">
          <Autocomplete
            options={nigerianSoups}
            renderInput={(params) => (
              <TextField {...params} label="Favourite Soup" />
            )}
        />
        </div>
      )
    }
    
    export default App;
    • `options` prop: This prop is an array of options the autocomplete component has. It can also be an array of objects, where each object has the property `label`. Material UI uses the value of the label as the default option. To change the default object property to use as an option, you need the `getOptionLabel` prop. It returns the preferred object property to use as an option.

      getOptionLabel={(options) => options.prefferedProperty}
    • `renderInput` prop: This prop is used to display the input bar for the Autocomplete. The proper way of using it is properly shown in the above Autocomplete code illustration.

This summarizes the simple way to use the Autocomplete component. There are other props a developer can add to the component to customize it further — for example giving it a random id, or making it accept multiple values — but once you have followed the steps above, you should have an up-and-running autocomplete component.

Material UI Autocomplete Modes

There are two major modes of input in the Material UI Autocomplete component. They are the Combo Box and Free Solo modes. This section of the article explains these different modes.

Combo box

In the combo box mode, which is the default mode, a value can only be selected from the set of suggested options. If the user’s input is not part of the suggested options in this mode, the input is not accepted. This mode is very similar to a drop-down list. Here is an illustration:

...
function App() {
  return (
    <Autocomplete
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: auto }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

Free Solo

In the Free Solo mode, the input box is not limited to accepting only pre-determined options — It can also accept a completely arbitrary value. To use this mode, set the `freeSolo` prop to `true`. Consider the following example:

...
function App() {
  return (
    <Autocomplete
      freeSolo
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

Important autocomplete component props

Apart from the few props like `freeSolo` and `getOptionLabel` mentioned previously, the MUI Autocomplete component comes with a lot of other props. This section will highlight the most useful props the component has, stating what they do and how to use them.

disableCloseOnSelect

This prop prevents the options of the Autocomplete from closing after an option has been selected by the user. Here is the prop in use:

...

function App() {
  return (
    <Autocomplete
      disableCloseOnSelect
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

clearOnEscape

Setting the prop to `true` allows a click of the “Escape” key on the keyboard to clear the autocomplete input.

...

function App() {
  return (
    <Autocomplete
      clearOnEscape
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

In this illustration, the user clicks the “Escape” key after selecting an option.

disableClearable

Using this prop removes the “X” button in the Autocomplete component. This prop also makes the input of the Autocomplete to not be clearable.

...
function App() {
  return (
    <Autocomplete
      disableClearable
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

includeInputInList

This prop adds the input bar to the list of options the user can navigate with up and down arrow keys.

...
function App() {
  return (
    <Autocomplete
      includeInputInList
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

autoComplete

When the `autoComplete` prop is set to true, options selected with arrow keys appear inline in the Autocomplete input bar.

...
function App() {
  return (
    <Autocomplete
      autoComplete
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

disableListWrap

The default behavior of the arrow keys up and down in the MUI Autocomplete component is to go through the options in a circular pattern. This means it can move from the last option to the first and vice versa.

The `disableListWrap` prop prevents this type of movement and makes it impossible to move through the first and last option on the list in one click.

...
function App() {
  return (
    <Autocomplete
      disableListWrap
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

openOnFocus

If this prop is set to true, the dropdown of options opens whenever the Autocomplete component is on focus.

...
function App() {
  return (
    <Autocomplete
      openOnFocus
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

autoHighlight

If this prop is set to true, then the first option is highlighted whenever a user wants to make an input.

...
function App() {
  return (
    <Autocomplete
      autoHighlight
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

autoSelect

This prop sets the highlighted option as the selected value if the Autocomplete loses focus.

...

function App() {
  return (
    <Autocomplete
      autoSelect
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

disabled

When the `disabled` prop is used, the component disables.This means that the user cannot interact with the component anymore.

...
function App() {
  return (
    <Autocomplete
      disabled
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

readOnly

Setting the `readOnly` prop to `true` makes it impossible for the user to set the value of the Autocomplete. You can use the prop `defaultValue` to set a default value for the Autocomplete. Using it together with `readOnly` means that the user cannot change the default value of the Autocomplete.

...
function App() {
  return (
    <Autocomplete
      readOnly
      options={nigerianSoups}
      defaultValue={nigerianSoups[5]}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

blurOnSelect

`blurOnSelect` is the prop that sets whether or not the input bar should blur after the user has selected an option. This prop can take in four different values.

  • `true`: This means that the input bar will always blur whenever the user selects an option.

  • `false`: This means that the input bar will never blur whenever the user selects an option.

  • `’mouse’`: This means that the input bar can only blur if the option is selected with a mouse.

  • `’touch’`: This value makes the input bar only blur when an option is selected using touch.

clearOnBlur

The `clearOnBlur` prop is useful in the Free Solo mode. It is used to instruct MUI Autocomplete to clear out the user’s input whenever the input bar is blurred, and no input is selected from the options.

In Combo Mode it is set by default to `true` but in Free Solo mode, it is set to `false`. Of course, you can change these boolean values.

selectOnFocus

With this prop, the application selects the text in the input whenever the input bar is in focus. This is a convenient way to clear text if the user wishes to do so without having to clear it one character at a time. It is set to `true` in Combo Box mode by default, and `false` in Free Solo Mode.

What is the difference between onChange and onInputChange props?

`onChange` and `onInputChange` are two event listener props used in Autocomplete, but the difference between them could be a little bit confusing. This section is going to differentiate them using a table.

onChange proponInputChange prop
Checks for a change in the value state — this state represents whatever value the user entersChecks for a change in the inputValue state — this state represents whatever is displayed on the input bar
Callback function accepts three parameters (event, value, and reason)Callback function can accept four parameters (event, value, reason, and optionally details)
Possible reasons for change this prop gives are “blur”, “clear”, “createOption”, “selectOption”, “removeOption”Possible reasons for change here are “input”, “reset”, and “clear”

How to allow users to add to Autocomplete Options

It is possible to add an arbitrary value a user enters to appear like an existing option in Autocomplete. We use the Free Solo mode to achieve this. To make the Free Solo mode behave like a Combo Box that can add custom options, these are the steps you can take:

  1. Set `freeSolo` prop to `true` as this needs Free Solo mode to work.

  2. Set `selectOnFocus` to true. It matches the Combo Box behavior.

  3. Allow `clearOnBlur` prop. It also matches the Combo Box behavior.

  4. Allow `handleHomeEndKeys`. This prop makes the “Home” and “End” keys navigate to the first and last autocomplete options respectively.

  5. Add a last option, for example: `Add “USER INPUT”

Here is a code illustration of how this could work:

import React, { useState } from "react";
import { Autocomplete, TextField, createFilterOptions } from "@mui/material";

const nigerianSoups = [
  { title: "Egusi Soup" },
  { title: "Ogbono Soup" },
  { title: "Efo riro" },
  { title: "Banga Soup" },
  { title: "Afang Soup" },
  { title: "Bitterleaf Soup" },
  { title: "Pepper Soup" },
  { title: "Okra Soup" },
  { title: "Ewedu Soup" },
  { title: "Uha Soup" },
  { title: "Black Soup" },
  { title: "Edikaikong Soup" },
  { title: "Miyan Kuka" },
  { title: "Ofe Nsala" },
  { title: "Ofe Ukazi" },
];

const filter = createFilterOptions();

function App() {
  const [value, setValue] = useState(null);

  return (
    <Autocomplete
      value={value}
      clearOnBlur
      freeSolo
      handleHomeEndKeys
      selectOnFocus
      onChange={(event, newValue) => {
        if (typeof newValue === "string") {
          setValue({ title: newValue });
        } else if (newValue && newValue.inputValue) {
          setValue({ title: newValue.inputValue });
        } else {
          setValue(newValue);
        }
      }}
      filterOptions={(options, params) => {
        const filtered = filter(options, params);
        const { inputValue } = params;

        const isExisting = options.some(
          (option) => inputValue === option.title
        );
        if (inputValue !== "" && !isExisting) {
          filtered.push({
            inputValue,
            title: `Add "${inputValue}"`,
          });
        }

        return filtered;
      }}
      getOptionLabel={(option) => {
        if (typeof option === "string") return option;
        if (option.inputValue) return option.inputValue;
        return option.title;
      }}
      options={nigerianSoups}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderOption={(props, option) => <li {...props}>{option.title}</li>}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

Here is how this could be displayed:

How to Group Autocomplete Options

Sometimes, the Autocomplete options can be too many and require some sort of grouping. The features of the Material UI extend into grouping options, meaning that the component has props to help us properly do this.

The most important prop to take note of to achieve this is the `groupBy` prop. It is a prop that accepts a function. The function it accepts should have a parameter `option`, and it should return the property to group the options by. Here is an example of how this could work in code:

...

const nigerianSoups = [...]

function App() {
  const options = nigerianSoups.map((value) => {
    const firstLetter = value[0].toUpperCase();
    return {
      firstLetter,
      value,
    };
  });

  return (
    <Autocomplete
      options={options.sort(
        (a, b) => -b.firstLetter.localeCompare(a.firstLetter)
      )}
      groupBy={(option) => option.firstLetter}
      getOptionLabel={(option) => option.value}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField {...params} label="Favorite Soup" size="small" />
      )}
    />
  );
}

export default App;

Another prop useful for grouping options is the `renderGroup` prop. This prop accepts a function with one parameter (an object) that represents a group and its children. The function is supposed to return a list item `<li>` that contains two things — a group header, and a list of its children. Check out this resource to learn more about how it works.

How to Load Autocomplete Options Asynchronously

Asynchronous requests are requests in a program that do not block other processes from running. These requests run in the background while the program continues its linear code execution, and the time before getting a response does not affect the execution of the code. In JavaScript, these requests could be fetch requests or Promises.

If the developer does not have the options for an Autocomplete beforehand or needs to fetch them from elsewhere, they could load the options asynchronously. The MUI Autocomplete component allows developers to do this as well. Here is a code example of this in action:

import React, { useEffect, useState } from "react";
import { Autocomplete, TextField, CircularProgress } from "@mui/material";

const countriesApi =
  "https://restcountries.com/v3.1/subregion/Western%20Africa";

function App() {
  const [open, setOpen] = useState(false);
  const [options, setOptions] = useState([]);
  const loading = open && options.length === 0;

  useEffect(() => {
    if (loading) {
      fetch(countriesApi)
        .then((res) => res.json())
        .then((data) => {
          setOptions(data);
        });
    }
  }, [loading]);

  return (
    <Autocomplete
      id="async-example"
      open={open}
      options={options}
      loading={loading}
      getOptionLabel={(option) => option.name.common}
      onOpen={() => setOpen(true)}
      onClose={() => setOpen(false)}
      sx={{ width: 300, marginTop: 6, marginX: "auto" }}
      renderInput={(params) => (
        <TextField
          {...params}
          label="Select a country"
          InputProps={{
            ...params.InputProps,
            endAdornment: (
              <>
                {loading ? (
                  <CircularProgress color="inherit" size={20} />
                ) : null}
                {params.InputProps.endAdornment}
              </>
            ),
          }}
          size="small"
        />
      )}
    />
  );
}

export default App;

This example calls an API that returns a list of countries. The Autocomplete Component then uses those countries as options. As you can see, some props that helped achieve this are `open`, `loading`, `onOpen`, and `onClose`. Here is the output of the code:

Best Practices for Using Material UI Autocomplete

This section teaches some of the best practices and patterns to implement while using the Material UI Autocomplete component. They are as follows:

  • Structure the Options Array properly: As seen in the examples, Autocomplete accepts an array of options for the `options` prop. The options must be an array, and using anything else throws an error. But, if the options are an array of objects, then all the objects need a `label`. If the objects don’t have a `label` property but have another property to identify what they represent individually, then the developer can set the label using `getOptionLabel`

  • Customize the Component to fit your Application: The Component has a default styling it comes with, as with every other material UI Component. However, customizing the component further to blend in with your application is recommended good practice. The easiest way to customize the component is using the `sx` prop.

  • Group options where necessary: In a long list of options, especially when some of the options share similar characteristics (First letter, similar properties), then it is recommended to group the options. Doing this improves the experience for the user, and massively reduces cognitive load.

Wrapping up Material UI Autocomplete

The article was a run down of the many capabilities of the Autocomplete component. It covered so many things such as why the autocomplete feature is useful, how to import the Material UI Autocomplete, different autocomplete modes, different autocomplete props, how to allow users to add to Autocomplete Options, How to group autocomplete options, how to load options asynchronously, and so much more.

That’s all for now for the Material UI Autocomplete component. As you can see, it is a robust component and has so many more features than were covered in the article (for example, allowing multiple values). You can find these features in the official Material UI Autocomplete Documentation. Don’t forget to check out PureCode, the tool that allows developers to generate components for their projects using AI, and saves them time.

Thank You for reading.

Further Reading

Here are a couple of resources you might need for further reading:

Amazing Agu

Amazing Agu