Programmatically set value in material-ui Autocomplete TextField

34,447

Solution 1

you can store desired value in state and pass it to auto complete component.

Import useState:

   import React, { useState } from 'react';

using useState:

   const [val,setVal]=useState({})

changin value on click of button

  const handleClick = () => {
    setVal(top100Films[0]);//you pass any value from the array of top100Films
   // set value in TextField from dropdown list
 };

and pass this value to component in render

 <Autocomplete
   value={val}
    options={top100Films}
    getOptionLabel={option => option.title}
    style={{ width: 300 }}
    renderInput={params => (
      <TextField
        {...params}
        label="Combo box"
        variant="outlined"
        fullWidth

      />
    )}
  />

Solution 2

if you want to show the default selected value in input you must also set inputValue property and onInputChange event of the Autocompelete component

changes in state:

const [value, setValue] = useState("");
const [inputValue, setInputValue] = useState("");

changes in handle click

const handleClick = () => {
   setValue(top100Films[0]);
   setInputValue(top100Films[0]);
};

changes in autocompelete

 <Autocomplete
    {...custom}
    value={value}
    inputValue={inputValue}
    onChange={(event, newValue) => {
      setValue(newValue);
    }}
    onInputChange={(event, newInputValue) => {
      setInputValue(newInputValue);
    }}

    options={top100Films}
    getOptionLabel={option => option.title}
    renderInput={(params) => (
      <TextField
        {...input}
        {...params}
        variant="outlined"
      />
    )}
  />

Solution 3

If you're here trying to test a change handler that is called from MUI's Autocomplete component:

In your setupTests.js file

import '@testing-library/jest-dom/extend-expect'

document.createRange = () => ({
  setStart: () => {},
  setEnd: () => {},
  commonAncestorContainer: {
    nodeName: 'BODY',
    ownerDocument: document
  }
})

In your test file:

import { render, fireEvent } from '@testing-library/react'

...

const { getByRole } = render(<MyComponentWithAutocomplete />)

const autocomplete = getByRole('textbox')

// click into the component
autocomplete.focus()

// type "a"
fireEvent.change(document.activeElement, { target: { value: 'a' } })

// arrow down to first option
fireEvent.keyDown(document.activeElement, { key: 'ArrowDown' })

// select element
fireEvent.keyDown(document.activeElement, { key: 'Enter' })

expect(autocomplete.value).toEqual('Arkansas')
expect(someChangeHandler).toHaveBeenCalledTimes(1)

For more examples, check out the tests in the library

Share:
34,447
Sergey
Author by

Sergey

Enthusiastic frontend developer from Russia. In love with React.js and would like to make the World a better place &lt;3. Green peace supporter. NBA &amp; skateboarding lover.

Updated on February 16, 2021

Comments

  • Sergey
    Sergey about 3 years

    In my React app I have an input which could take value from the dropdown list. For that putpose I use material-ui Autocomplete and TextField components.

    Question: how can I programmaticaly set an input value by clicking on the button without choosing from the dropdown list? For example, I want to set "The Godfather" from the example and this value should be visually seen in the input.

    Codesandbox example here

    import React from "react";
    import Autocomplete from "@material-ui/lab/Autocomplete";
    import { TextField, Button } from "@material-ui/core";
    
    export default function ComboBox() {
      const handleClick = () => {
        // set value in TextField from dropdown list
      };
    
      return (
        <React.Fragment>
          <Autocomplete
            options={top100Films}
            getOptionLabel={option => option.title}
            style={{ width: 300 }}
            renderInput={params => (
              <TextField
                {...params}
                label="Combo box"
                variant="outlined"
                fullWidth
              />
            )}
          />
          <Button onClick={handleClick}>Set value</Button>
        </React.Fragment>
      );
    }
    
    // Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
    const top100Films = [
      { title: "The Shawshank Redemption", year: 1994 },
      { title: "The Godfather", year: 1972 },
      { title: "The Godfather: Part II", year: 1974 },
      { title: "The Dark Knight", year: 2008 }
    ];
    
  • Fogus
    Fogus almost 4 years
    If your Autocomplete can have multiple values (attribute multiple is set), then the value to the value attribute should be an array. For the above case it would be setVal([top100Films[0]]); instead of setVal(top100Films[0]);
  • Aquib
    Aquib almost 4 years
    Passing an array does not render anything.
  • africola
    africola almost 3 years
    Note that value in this example would be an array of objects, while inputValue should be a string: material-ui.com/api/autocomplete Thus handleChange should set inputValue using the title property, e.g. setInputValue(top100Films[0].title
  • hane Smitter
    hane Smitter over 2 years
    i did this when using mui autocomplete and formik. When i set the default value on the autocomplete, formik state is not updated to take the default selected value into its state. Any idea of how this could be done