React Formik Material UI Autocomplete: How can I populate value inside of autocomplete from localStorage?
Asked Answered
W

1

19

So, I'm trying to create form with Formik and Material UI. For all the fields everything is working as it should but the problem is with Autocomplete. I cannot find the way to populate the field from the localStorage. I tried everything, from putting the value props, inputValue, defaultValue, etc but nothing seems to work.

import React from 'react'
import { Grid } from '@material-ui/core'
import { Autocomplete } from '@material-ui/lab'
import { Formik, Form, Field } from 'formik'
import { TextField } from 'formik-material-ui'
import * as yup from 'yup'
import { nationality } from '../../constants/nationality'
import Button from '../Button/Button'

export default function ForeignAddress () {

  let localStorageData = localStorage.getItem('foreignAddress'),
    retrivedData = JSON.parse(localStorageData)


  const handleNextClick = () => {
    console.log('clicked next')
  }

  const handleBackClick = () => {
    console.log('clicked back')
  }

  const validationSchema = yup.object({
    streetName: yup.string().required('Street name is required'),
    streetNumber: yup.string().required('Street number is required'),
    postalCode: yup.string().required('Postal code is required'),
    city: yup.string().required('City is required'),
    country: yup.string().required('Country is required'),
  })

  console.log(retrivedData)

  return (
    <React.Fragment>
      <div className="pages-wrapper address">
        <Formik
          initialValues={retrivedData ? retrivedData : {streetName: '', streetNumber: '', postalCode: '', city: '', coAddress: '', country: ''}}
          onSubmit={(data) => {
            console.log(data)
            localStorage.setItem('foreignAddress', JSON.stringify(data))
            handleNextClick()
          }}
          validationSchema={validationSchema}
        >
          {({setFieldValue}) => (
            <Form>
              <Grid container spacing={3}>
                <Grid item xs={12} md={8}>
                  <Field component={TextField} name="streetName" label="Street Name" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={4}>
                  <Field component={TextField} name="streetNumber" label="Street Number" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={4}>
                  <Field component={TextField} name="postalCode" label="Postal Code" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={8}>
                  <Field component={TextField} name="city" label="City" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={6}>
                  <Field component={TextField} name="coAddress" label="C/O Address" variant="outlined" fullWidth />
                </Grid>
                <Grid item xs={12} md={6}>
                  <Autocomplete
                    id="foreignCountry"
                    className="country-select"
                    name="country"
                    options={nationality}
                    getOptionLabel={option => option.label}
                    onChange={(e, value) => {
                      console.log(value)
                      setFieldValue("country", value.code)
                    }}
                    renderInput={params => (
                      <Field component={TextField} {...params} name="country" label="Country" variant="outlined" fullWidth/>
                    )}
                  />
                </Grid>
              </Grid>
              <div className="button-wrapper">
                <Button label="Back" go="back" handleClick={handleBackClick}/>
                <Button label="Next" go="next" type="submit" />
              </div>
            </Form>
          )}
        </Formik>
      </div>
    </React.Fragment>
  )
}

EDIT:

Thanks to @Vencovsky i was able to get it done

in case someone in the future needs this here is the working code. Just change Autocomplete component to

<Autocomplete
  id="foreignCountry"
  className="country-select"
  name="country"
  options={nationality}
  getOptionLabel={option => option.label}
  defaultValue={values.country}
  onChange={(e, value) => {
    console.log(value)
    setFieldValue("country", value)
}}
  renderInput={params => (
    <Field component={TextField} {...params} name="country" label="Country" variant="outlined" fullWidth/>
)}
/>

and in the Formik props just add values prop

{({setFieldValue, values}) => (
   <Form>,...
Wham answered 9/12, 2019 at 13:26 Comment(3)
thanks for sharing, helped me a lot :+1Giraud
Thanks for pointing me in the right direction!Screak
Thanks, It works for both single selection and multiple selections.Derma
T
17

Edit:

There is a few thing you need to change.

First you can't just store the code to load it later, you need to store everything (the hole value object) from the options.

Change the initial value of country: '' to country: {code: "", label: "", phone: ""} which is all the default value of the options.

Then to load the value correctly you should pass value={values.country} where values comes from formik props.

And on onChange you should save the hole value onChange={(e, value) => {setFieldValue("country", value); }}

But you are also importing and using some wrong things like

  <Field
    component={TextField}
    {...params}
    name="country"
    label="Country"
    variant="outlined"
    fullWidth
  />

Where Field is form formik and TextField from formik material ui.

Not sure why you use it like that, but I have changed it.

Here is a working example

Thrombocyte answered 9/12, 2019 at 13:38 Comment(10)
Thanks for reply. But the values are changing, that's not the problem. What i'm trying to get is just to show the value from localStorage in Autocomplete Text Field. All other fields are getting populated.Wham
What is not working? Can you please show how is the data from localStorage?Thrombocyte
{"streetName":"asd","streetNumber":"asd","postalCode":"sad","city":"asd","coAddress":"","country":"RS"}, and like i said, when component renders, all the fields are populated except autocomplete field.Wham
@Wham check my edit, you are saving the data wrongThrombocyte
no, still nothing. i've made a sandbox codesandbox.io/s/dank-https-tykxu so you can see whats wrong. Try clicking next, and look at the localStorage. You will se the country has value. After that try refreshing the page and you will se that all the fields gets updated except Country field. thanks againWham
@Wham your link is broken/emptyThrombocyte
@Wham please check my answer and my codesandbox, now it's workingThrombocyte
@Wham if that solved your problem, please considerer upvoting and marking the answer as accepted, thanks ;)Thrombocyte
Ops, Just a secThrombocyte
@Wham i realized you made a big mistake in the imports, now it's working and it's fixedThrombocyte

© 2022 - 2024 — McMap. All rights reserved.