使用 Material UI 的自动完成功能,使用 Formik 在下拉列表中显示不同的值,但在 formik 状态下设置不同的值

Using Material UI's Autocomplete using Formik to display different value in dropdown but set different value in formik state

我正在尝试将 Material UI 的自动完成功能与 Formik 一起使用。这是我编写的用于 Formik 的自定义自动完成组件。

import React from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import TextField from "@material-ui/core/TextField";
import { fieldToTextField } from "formik-material-ui";

const FormikAutocomplete = ({ textFieldProps, ...props }) => {
  const {
    form: { setTouched, setFieldValue },
  } = props;
  const { error, helperText, ...field } = fieldToTextField(props);
  const { name } = field;

  return (
    <Autocomplete
      {...props}
      {...field}
      onChange={(_, value) =>
        setFieldValue(name, value)
      }
      onBlur={() => setTouched({ [name]: true })}
      renderInput={(props) => (
        <TextField
          {...props}
          {...textFieldProps}
          helperText={helperText}
          error={error}
        />
      )}
    />
  );
};

export default FormikAutocomplete;

组件的调用方式如下

<Field
  name="title"
  component={FormikAutocomplete}
  options={gender}
  getOptionLabel={(option) => option.title_name_long}
  textFieldProps={{
    label: "Title",
    required: true,
    variant: "outlined",
    margin: "dense",
  }}
/>

现在我打算做的是:如果我有一个像

这样的对象
gender=[{gender_name_short:"F",gender_name_long:"Female},{gender_name_short:"M",gender_name_long:"Male}]

我希望自动完成下拉菜单显示男、女选项。 但是我希望 formik 状态在从下拉列表中选择后分别保存 M、F。目前整个对象都被保存了。

如何做到这一点?

FormikAutocomplete组件中,

  • 在自动完成的 onChange 中使用 setFieldValue
  • getOptionLabel中使用gender_name_long显示Male,Female
  • getOptionSelected中使用gender_name_short来使用MF

最后,当您提交时,您将看到 M/F 而不是 Male/Female

Working demo

const gender = [
  { gender_name_short: "F", gender_name_long: "Female" },
  { gender_name_short: "M", gender_name_long: "Male" }
];
const validationSchema = object().shape({
  // genderObj: array().required("At least one gender is required")
});

const initialValues = {
  username: "abc",
  country: "",
  gender: "M",
  birthdate: null
};

const FormikAutocomplete = ({ textFieldProps, ...props }) => {
  const {
    form: { setTouched, setFieldValue }
  } = props;
  const { error, helperText, ...field } = fieldToTextField(props);
  const { name } = field;

  return (
    <Autocomplete
      {...field}
      {...props}
      onChange={(_, data) => {
        setFieldValue("gender", data.gender_name_short);
      }}
      onBlur={() => setTouched({ [name]: true })}
      // getOptionLabel={item => item.gender_name_long} //<----see here
      getOptionLabel={item => {
        // console.log( '====>' , typeof item === "string" ? props.options.find(i => i.gender_name_short === item).gender_name_long : item.gender_name_long)
        return typeof item === "string"
          ? props.options.find(i => i.gender_name_short === item)
              .gender_name_long
          : item.gender_name_long;
      }}
      // getOptionLabel={item => typeof item === 'string' ? props.options.find(i => i.gender_name_short === item).gender_name_long : item.gender_name_long}
      getOptionSelected={(item, current) => {
        return item.gender_name_short === current;
      }}
      // defaultValue={'hi'}
      renderInput={props => (
        <TextField
          {...props}
          {...textFieldProps}
          helperText={helperText}
          error={error}
        />
      )}
    />
  );
};

const SimpleFormExample = () => (
  <div>
    <h1>Simple Form Example</h1>
    <Formik
      initialValues={initialValues}
      validationSchema={validationSchema}
      validateOnBlur={false}
      validateOnChange
      onSubmit={(values, { resetForm, setSubmitting }) => {
        console.log(values);
        resetForm();
        // setSubmitting(false);
      }}
    >
      {formik => (
        <Form>
          <Field
            name="gender"
            component={FormikAutocomplete}
            label="gender"
            options={gender}
            textFieldProps={{
              fullWidth: true,
              margin: "normal",
              variant: "outlined"
            }}
            // multiple
          />

          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  </div>
);

export default SimpleFormExample;