34

Does anyone know how to add a default value to the Autocomplete component? The component have a dataSource, and I'd like to load the page with a specific item already selected(e.g. fill the text field with the selected item's text and it's value already set).

Does anyone knows how? Big thanks for any help <3

13 Answers 13

11

I tried all the above solutions and nothing worked. Perhaps the API has changed since then.

I finally figured out a solution. It's not so elegant, but in principle it makes sense. In my case the options are objects. I just had to set the "value" prop using the exact item from my options array. This way componentDidMount and getOptionSelected aren't needed.

Autocomplete is wrapped inside another component in our case. This is the main code:

class CTAutoComplete extends React.PureComponent {

  getSelectedItem(){
    const item = this.props.options.find((opt)=>{
      if (opt.value == this.props.selectedValue)
        return opt;
    })
    return item || {};
  }

  render() {
    return (
        <Autocomplete
            id={this.props.id}
            className={this.props.className}
            style={{ width: '100%' }}
            options={this.props.options}
            getOptionLabel={this.props.getOptionLabel}
            renderInput={params => (
                <TextField {...params} label={this.props.label} variant="outlined" />
            )}
            onChange={this.props.onChange}
            value={this.getSelectedItem()}
        />
    );
  }
}

IMPORTANT: When setting "value", you have to make sure to put the null case " || {} ", otherwise React complains you are changing from an uncontrolled to controlled component.

Sign up to request clarification or add additional context in comments.

Comments

9

You can achieve this by setting the appropriate state in componentDidMount, for example:

componentDidMount() {
    // load your items into your autocomplete

    // set your default selected item
    this.setState({ allItems: [itemYouWantToSet], selectedItem: item.name, selectedItemId: item.id }
}

render() {
    return (
		<Autocomplete
		    value={this.state.selectedItem}
		    items={this.state.allItems}
		    getItemValue={(item) => item.name}
		    onSelect={(value, item) => {
		        this.setState({ selectedItem: value, selectedItemId: value, allItems: [item] });
		    }}
		/>
    )
}

Then your item is correctly selected from the list of available options when it loads.

3 Comments

This should be accepted as answered to help others like me. According to doc: "The value must have reference equality with the option in order to be selected. You can customize the equality behavior with the getOptionSelected prop." If you use an array of objects, yo must use an object in the value={obj} property.
Not sure if the API changed, but I don't see any 'getItemValue' prop for Autocomplete component in docs: material-ui.com/api/autocomplete Just tested and get this in the console: "Warning: React does not recognize the getItemValue prop on a DOM element."
Please state which MUI version does this solution is for
8

you can provide the defaultValue prop for AutoComplete.

like defaultValue={{ label: 'Select an option', id: 'someID' }}

<Autocomplete
    multiple
    id="tags-outlined"
    options={this.state.categories}
    getOptionLabel={(option) => option.category_name}
    onChange={this.handleAutocomplete}
    defaultValue={'yourDefaultStringValue'} //put your default value here. It should be an object of the categories array.
    filterSelectedOptions
    renderInput={(params) => (
        <TextField
            fullWidth
            {...params}
            variant="outlined"
            label="Add Categories"
            placeholder="Category"
            required        
        />
    }
/>

Comments

6

This approach works for me (using hooks):

First of all define the options you need in a variable:

const genderOptions = [{ label: 'M' }, { label: 'V' }];

Second you can define a hook to store the selected value (for example store it in session storage for when the page refreshes, or use useState directly):

const age = useSessionStorage('age', '');

Next you can define your Autocomplete as follows (notice the default values in value and getOptionLabel, if you omit those you'll get those controlled to uncontrolled warnings):

  <Autocomplete
    id="id"
    options={ageOptions}
    getOptionLabel={option => option.label || ""}
    value={ageOptions.find(v => v.label === age[0]) || {}} // since we have objects in our options array, this needs to be a object as well
    onInputChange={(_, v) => age[1](v)}
    renderInput={params => (
      <TextField {...params} label="Leeftijd" variant="outlined" />
    )}
  />

1 Comment

After googling for some time I finally found an answer that solved my problem. Thank you @Simon Temmerman
2

The api docs suggest the best approach in the current version (June 2022) is to use value and isOptionEqualToValue.

So for example, if I have a list of users and am choosing which user this thing is assigned to:

  const [assignedTo, setAssignedTo] = useState(initialOption);

  return (<Autocomplete
    options={users.map((i) => ({
        label: i.name,
        value: i._id,
    }))}
    isOptionEqualToValue={(o, v) => o.value === v.id}
    value={assignedTo}
    onChange={(evt, val) => setAssignedTo(val)}
    renderInput={(params) => (
        <TextField {...params} label="Assigned To" />
    )}
  />);

1 Comment

This did the trick for me! Thanks so much :)
1

It is tricky specially in case of you are using along with filter option which load API on every filter. I was able to load initial value by setting up within state and onInputChange option.

Below is code that work for me or click below link for full working demo.

https://codesandbox.io/s/smoosh-brook-xgpkq?fontsize=14&hidenavigation=1&theme=dark

import React, { useState, useEffect } from "react";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import Autocomplete from "@material-ui/lab/Autocomplete";

export default function CreateEditStrategy({ match }) {
  const [user, setUser] = useState({
    _id: "32778",
    name: "Magic User's Club!"
  });
  const [filter, setFilter] = useState("");
  const [users, setUsers] = useState([]);
  const [openAutoComplete, setOpenAutoComplete] = React.useState(false);

  useEffect(() => {
    (async () => {
      //Will not filter anything for testing purpose
      const response = await fetch(
        `https://api.tvmaze.com/search/shows?q=${filter}`
      );
      const shows = await response.json();

      setUsers(
        shows.map((a, i) => {
          return { _id: a.show.id, name: a.show.name };
        })
      );
    })();
  }, [filter]);
  return (
    <div>
      <Typography variant="h6">Autocomplete</Typography>
      <Autocomplete
        open={openAutoComplete}
        onOpen={() => setOpenAutoComplete(true)}
        value={user}
        inputValue={filter}
        onClose={() => setOpenAutoComplete(false)}
        onChange={(event, user) => {
          if (user) setUser(user);
          else setUser({ _id: "", name: "" });
        }}
        onInputChange={(event, newInputValue) => setFilter(newInputValue)}
        getOptionSelected={(option, value) => option.name === value.name}
        getOptionLabel={(option) => option.name}
        options={users}
        renderInput={(params) => (
          <TextField
            {...params}
            label="Asynchronous"
            variant="outlined"
            InputProps={{
              ...params.InputProps
            }}
          />
        )}
      />
    </div>
  );
}

Comments

0

Call your component like this

<SelectCountryAutosuggest searchText="My Default Value" />

Make sure you apply the default value to state on class load

class SelectCountryAutosuggest extends React.Component {
  state = {
    value: this.props.searchText, //apply default value instead of ''
    suggestions: [],
  };
...
}

Comments

0

We can setup initial value through value property of Autocomplete component

<Autocomplete
   fullWidth={true}
   label={'Location'}
   margin={'noraml'}
   multiple={false}
   name={'location'}
   getOptionSelected={useCallback((option, value) => option.value === value.value)}
   value={formValues.location === '' ? {label: ''} : {label: formValues.location}}
   options={location}
   ref={locationRef}
   onChange={useCallback((e, v) => handleInputChange(e, v))}
/>

Comments

0
<Autocomplete
    name="category_id"
    options={this.state.productList}
    //this selectPoduct is the filterd object of productList
    value={selectProduct || {product_name: ""}}
    getOptionLabel={(options) =>
    options.product_name
    }
    renderInput={(params) => (
    <TextField
    {...params}
    variant="outlined"
    />
    )}
    onChange={(e, newValue={}) => {
    this.handleChange({target: {name: 
    "product_id", value: newValue.id || ""}});
    }}
    size="small"
/>

100% working for mui v4

Comments

-1

You can use the searchText property.

<AutoComplete searchText="example" ... />

3 Comments

Thanks for the response. Sure, I tried that, but I'd like to set it's value too. Actually I was looking for a prop to set the value and by setting the value it would set the text in the TextField also. The problem of setting just the the searchText is that you have to loop in all dataSource to find the value that matches the text. In my case I'm loading the form from with data coming from a server that already have the value, but I need to populate it's TextField and also set it's value in case the user doesn't change the field so the field it's ready to be sent.
@BetuUuUu have you solved this issue? I'm facing the same problem
I did not, I kept filling the searchText prop, the value is set trough redux-form library.
-1

Try this...

componentWillReceiveProps(nextProps) {
    let value = nextProps.value
    if (value) {
      this.setState({
        value: value
      })
    }
  }

Comments

-2

onUpdateInput worked for me - for anyone looking through all this as I was

2 Comments

Hello! I haven't been using this library from a long time now; but I'll give you an +1 for the contribution :)
There is no onUpdateInput property on the Autocomplete component. material-ui.com/api/autocomplete
-3

Have you tried setting the searchText prop dynamically? You can pass the value you want to set to the Autocomplete component as the searchText prop. Something like,

<Autocomplete
  searchText={this.state.input.name} // usually value={this.state.input.name}
/>

By default, it'll have the initial value set into the TextField of the Autocomplete component but when the user makes any modifications, it calls up the Autocomplete options depending on the dataSource prop.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.