How to pick specific field of an object array using the material ui autocomplete component

Asked

Viewed 192 times

-2

I have a Material UI autocomplete component, created using the package formik-material-ui. The component renders an array of model objects below:

const teams = [
  {id: 1, name: 'Barcelona'},
  {id: 2, name: 'Real Madrid'},
];

When to change the selection (onInputChange) of Autocomplete, I need to get only the ID of the selection, what happens is that I’m taking the name.

Follow the full code: Edit autocomplete material-ui example (forked).

What would be the correct procedure to get the ID?


import * as React from 'react';
import {render} from 'react-dom';
import {Formik, Form, Field} from 'formik';
import {Button, LinearProgress} from '@material-ui/core';
import MuiTextField from '@material-ui/core/TextField';
import {
  Autocomplete,
  AutocompleteRenderInputParams,
} from 'formik-material-ui-lab';
import Box from '@material-ui/core/Box';

const teams = [
  {id: 1, name: 'Barcelona'},
  {id: 2, name: 'Real Madrid'},
];

const App = () => {
  const [selected, setSelected] = React.useState('');

  const handleShowId = React.useCallback((event, value) => {
    alert(value.id);
    setSelected(event.target);
  }, []);

  console.log(selected);

  return (
    <Formik
      initialValues={{
        autocomplete: [],
      }}
      onSubmit={(values, {setSubmitting}) => {
        setTimeout(() => {
          setSubmitting(false);
          alert(JSON.stringify(values, null, 2));
        }, 500);
      }}
    >
      {({submitForm, isSubmitting, touched, errors}) => (
        <Form>
          {isSubmitting && <LinearProgress />}
          <Box margin={1}>
            <Field
              name="autocomplete"
              component={Autocomplete}
              options={teams}
              value={selected}
              getOptionLabel={(option: any) => option.name}
              style={{width: 300}}
              onChange={handleShowId}
              renderInput={(params: AutocompleteRenderInputParams) => (
                <MuiTextField
                  {...params}
                  error={touched['autocomplete'] && !!errors['autocomplete']}
                  helperText={touched['autocomplete'] && errors['autocomplete']}
                  label="Autocomplete"
                  variant="outlined"
                />
              )}
            />
          </Box>
          <Box margin={1}>
            <Button
              variant="contained"
              color="primary"
              disabled={isSubmitting}
              onClick={submitForm}
            >
              Submit
            </Button>
          </Box>
        </Form>
      )}
    </Formik>
  );
};

render(<App />, document.getElementById('root'));
  • 1

    https://material-ui.com/pt/components/autocomplete/#controllable-States

  • onChange instead of onInputChange returns the selected object

  • Right, I had thought about this approach, the problem is that the field is clearing after onChange. I upgraded the SANDBOX.

2 answers

3


I believe the following code can solve your problem

import * as React from 'react';
import {render} from 'react-dom';
import {Formik, Form, Field} from 'formik';
import {Button, LinearProgress} from '@material-ui/core';
import MuiTextField from '@material-ui/core/TextField';
import {
  Autocomplete,
  AutocompleteRenderInputParams,
} from 'formik-material-ui-lab';
import Box from '@material-ui/core/Box';

const teams = [
  {id: 1, name: 'Barcelona'},
  {id: 2, name: 'Real Madrid'},
];

const App = () => {
  const handleShowId = React.useCallback((event, value) => {
    alert(JSON.stringify(value.id));
  }, []);

  return (
    <Formik
      initialValues={{
        autocomplete: [],
      }}
      onSubmit={(values, {setSubmitting}) => {
        setTimeout(() => {
          setSubmitting(false);
          alert(JSON.stringify(values, null, 2));
        }, 500);
      }}
    >
      {({submitForm, isSubmitting, touched, errors}) => (
        <Form>
          {isSubmitting && <LinearProgress />}
          <Box margin={1}>
            <Field
              name="autocomplete"
              component={Autocomplete}
              options={teams}
              getOptionLabel={(option: any) => option.name}
              style={{width: 300}}
              onChange={handleShowId}
              renderInput={(params: AutocompleteRenderInputParams) => (
                <MuiTextField
                  {...params}
                  error={touched['autocomplete'] && !!errors['autocomplete']}
                  helperText={touched['autocomplete'] && errors['autocomplete']}
                  label="Autocomplete"
                  variant="outlined"
                />
              )}
            />
          </Box>
          <Box margin={1}>
            <Button
              variant="contained"
              color="primary"
              disabled={isSubmitting}
              onClick={submitForm}
            >
              Submit
            </Button>
          </Box>
        </Form>
      )}
    </Formik>
  );
};

render(<App />, document.getElementById('root'));

As the above comment says the property onInputChange represents the value inside the text box, while the onChange represents the object itself. I hope to have helped

  • Right, I had thought about this approach, the problem is that the field is clearing after onChange. I upgraded the SANDBOX.

  • @Fred Now I can’t test because I’m busy but I believe if you pass event.preventDefault() for the callback should work

  • As you can see by testing this code the browser reloads the page because this is the default behavior and with the event.preventDefault() we stopped it from happening

  • 1

    Did it work with Event.preventDefault() ? I tried it here and it didn’t work. I think it’s an Autocomplete bug from the formik-material-ui-lab package.

  • I did the following, I created a state by initializing it as empty, in onChange, I set the state to value.name. And I pass this value to the Autocomplete value property. That’s how it worked. Thanks for the help!

  • 1

    Thank you. Good to know if I will use this in some project will be very useful

Show 1 more comment

2

According to the link sent by Rafael Tavares in your comment, the documentation specifies that in order to capture the selected object you need to use the onChange method instead of onInputChange. Print do atributo onInputChange

If you swap onInputChange for onChange its value variable will return the whole object instead of only the name. Print da documentação onChange

https://material-ui.com/pt/components/autocomplete/#controllable-States

Browser other questions tagged

You are not signed in. Login or sign up in order to post.