Cant get event.target.value using select item from material-ui autocomplete with onchange

10,322

Solution 1

Edit: Using e.target.textContent will do the trick.
Here is a live Codesandbox to check the code (modified some parts, applying the tips below and some other things).


Don't mutate state manually like this:
this.state.itemSelected = true

Use setState (like you're already doing for other state items):

 updateState(e) {
    this.setState({ inputVal: e.target.value, itemSelected: true });
    console.log(e.target.value);
    // eventually I want to render a DIV with data from the selected value
  }

Also a tip, you can use array destructuring:

const {isLoaded, itemSelected} = this.state;

Instead of

var isloaded = this.state.isLoaded;
var itemSelected = this.state.itemSelected;

Solution 2

onChange signature: function(event: object, value: any) => void

Here's an example:

import React from 'react';
import Chip from '@material-ui/core/Chip';
import Autocomplete from '@material-ui/lab/Autocomplete';
import TextField from '@material-ui/core/TextField';

export default class Tags extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tags: []
    };
    this.onTagsChange = this.onTagsChange.bind(this);
  }

  onTagsChange = (event, values) => {
    this.setState({
      tags: values
    }, () => {
      // This will output an array of objects
      // given by Autocompelte options property.
      console.log(this.state.tags);
    });
  }

  render() {
    return (
      <div style={{ width: 500 }}>
        <Autocomplete
          multiple
          options={top100Films}
          getOptionLabel={option => option.title}
          defaultValue={[top100Films[13]]}
          onChange={this.onTagsChange}
          renderInput={params => (
            <TextField
              {...params}
              variant="standard"
              label="Multiple values"
              placeholder="Favorites"
              margin="normal"
              fullWidth
            />
          )}
        />
      </div>
    );
  }
}

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 },
  { title: '12 Angry Men', year: 1957 },
  { title: "Schindler's List", year: 1993 },
  { title: 'Pulp Fiction', year: 1994 },
  { title: 'The Lord of the Rings: The Return of the King', year: 2003 },
  { title: 'The Good, the Bad and the Ugly', year: 1966 },
  { title: 'Fight Club', year: 1999 },
  { title: 'The Lord of the Rings: The Fellowship of the Ring', year: 2001 },
  { title: 'Star Wars: Episode V - The Empire Strikes Back', year: 1980 },
  { title: 'Forrest Gump', year: 1994 },
  { title: 'Inception', year: 2010 },
];
Share:
10,322
Sean Wayland
Author by

Sean Wayland

Updated on June 05, 2022

Comments

  • Sean Wayland
    Sean Wayland almost 2 years

    *** CODE UPDATED FROM SUGGESTIONS ****** I am learning to use material-ui. I cant find many examples of combining it with event handling. I have used an autocomplete and a textfield to create a suggested list of data fetched from an API. I can render the selected list but on clicking one of the selections I can't get the value clicked on to be passed to a member function of the react class. Do I need to bind the event properly to the autocomplete? How should I do this. Line 25 in my code logs the event target to the console but it is always 0 ( null I assume ) . How can I set the value of the this.state.data to the clicked option ?

    I tried adding autoSelect={true}

    I also tried moving this line of code into the textarea .
    onChange={this.updateState}

    import React from "react"
    import TextField from '@material-ui/core/TextField';
    import Autocomplete from '@material-ui/lab/Autocomplete';
    
    class App extends React.Component {
    
    
        constructor(props) {
            super(props);
    
            this.state = {
                data: null,
                isLoaded: false,
                itemSelected: false,
                inputVal: ''}
    
                this.updateState = this.updateState.bind(this)
    
            };
    
            updateState(e) {
                e.persist()
                const newValue = e.target.value
                this.setState({inputVal: newValue, itemSelected: true});
                console.log(e.target.value);
    
                // eventually I want to render a DIV with data from the selected value
            }
    
            /// fetch some data
    
        componentDidMount() {
            fetch('http://jsonplaceholder.typicode.com/posts')
                .then(response => response.json())
                /* .then(json => console.log(json)) */
    
                .then(data => this.setState({data, isLoaded: true}));
        }
    
        render() {
    
            const {isLoaded, itemSelected} = this.state;
    
    
    
    
            if (!isLoaded) {
                return <div> loading ...</div>;
            } else if (itemSelected) {
                return <div> item selected </div>
            } else {
                const limo = this.state.data;
                return (
                    <div>
    
                        <Autocomplete
                            freeSolo
                            disableClearable
                            autoSelect={true}
                            id = "limoSelect"
                            onChange={this.updateState}
                            value = {this.state.inputVal}
                            options={limo.map(option => "body: '" + option.body + '\n' + "'      id: " + option.id)}
                            renderInput={params => (
    
                                <TextField
                                    {...params}
                                    label="Type In Content"
                                    id="limoText"
                                    value = ''
                                    autoSelect={true}
                                    margin="normal"
                                    variant="outlined"
                                    fullWidth
                                    InputProps={{...params.InputProps, type: 'search'}}
    
                                />
    
    
                            )}
                        />
                    </div>
                );
    
            }
        }
    }
    
    App.defaultProps = {}
    
    export default App;
    

    console logs zero . When you click on the option the updateState is called and this variable is being set this.state.itemSelected = true; No error messages . I am hoping the console.log in the updateState can be made to log the clicked item !

    • EduardoSaverin
      EduardoSaverin over 4 years
      try using e.persist() before fetching value
    • Sean Wayland
      Sean Wayland over 4 years
      Thanks Eduardo. I tried this code but still logging zero : updateState(e) { e.persist() this.setState({inputVal: e.target.value, itemSelected: true}); console.log(e.target.value); // eventually I want to render a DIV with data from the selected value }
    • Sean Wayland
      Sean Wayland over 4 years
      I also tried storing the value at the top of the function to try and deal with what might be an asynchronous issue : const newValue = e.target.value . That didn't help either.
    • Nicolas Hevia
      Nicolas Hevia over 4 years
      I think I've found a solution, check my answer's edit
    • Sean Wayland
      Sean Wayland over 4 years
      Thanks !! That's a great help Nicolas. I am still trying to dig into that event and get the id of the clicked on option. I tried logging console.log(e.target) : I wonder how I can access the value of the "data-option-index" . If I could pull that id out I could render what I need which is all the info from the json data. <li tabindex="-1" role="option" id="limoSelect-option-4" data-option-index="4" aria-disabled="false" aria-selected="false" class="MuiAutocomplete-option" data-focus="true">body: 'repudiandae veniam quaerat
    • Nicolas Hevia
      Nicolas Hevia over 4 years
      @SeanWayland You can get it using console.log(e.target.getAttribute("data-option-index")). If it solved your issue, please accept my answer as the solution.
  • Sean Wayland
    Sean Wayland over 4 years
    Thanks Nicolas those are good suggestions. Using your updateState method the console.log(e.target.value) produces a zero. The clicked on option is not being passed up to that function I think.
  • Sean Wayland
    Sean Wayland over 4 years
    the const suggestion created this error . "Line 49:14: 'isloaded' is not defined no-undef"
  • Nicolas Hevia
    Nicolas Hevia over 4 years
    The error is because you had "var isloaded" and state is "isLoaded". Change isloaded to IsLoaded here if (!isloaded)