Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically set value in material-ui Autocomplete TextField

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 }
];
like image 220
Sergey Avatar asked Jan 17 '20 07:01

Sergey


4 Answers

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"
      />
    )}
  />
like image 90
parichehr.mohebbi Avatar answered Oct 21 '22 17:10

parichehr.mohebbi


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

      />
    )}
  />
like image 21
Jatin Parmar Avatar answered Oct 21 '22 16:10

Jatin Parmar


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

like image 1
Devin Clark Avatar answered Oct 21 '22 16:10

Devin Clark


No one gives the correct answer...

const options = [
  { label: "A", value: 1 },
  { label: "B", value: 2 },
  { label: "A", value: 3 },
];

function MyInput() {
  const [value, setValue] = useState(options[0].value);

  return (
    <Autocomplete
      value={options.find((option) => option.value === value)}
      onChange={(_, v) => setValue(v?.value)}
      options={options}
      getOptionLabel={(option) => option.label}
      renderInput={(params) => (
        <TextField {...params}/>
      )}
    />
  )
}
like image 1
user2790103 Avatar answered Oct 21 '22 15:10

user2790103