在Materialik中使用Material-UI的自动完成组件

时间:2019-12-06 17:19:00

标签: reactjs material-ui formik

当前尝试在Formik中使用Material UI的Autocomplete组件。到目前为止,Formik可以很好地处理文本字段和Material-UI中的传统选择之类的事情。并非如此。 Formik的onChange处理程序似乎并未更新我的city_id的值。我知道Autocomplete仍然不是Material-UI核心库的一部分,但是目前仍在查看是否有可能出现这种情况。

import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form } from 'formik';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import Button from '@material-ui/core/Button';

import { cities } from '../data/cities';

import "./styles.css";

const initialValues = {
  city_id: '',
};

const submit = params => {
  alert(`Value for city_id is: ${params.city_id}`);
};

function App() {
  return (
     <Formik
      initialValues={ initialValues }
      onSubmit={ submit }
    >
      {({
        handleChange,
        values,
      }) => (
        <Form>
          <Autocomplete
            id="city_id"
            name="city_id"
            options={ cities }
            groupBy={ option => option.state }
            getOptionLabel={ option => option.name }
            style={{ width: 300 }}
            renderInput={params => (
              <TextField
                { ...params }
                onChange={ handleChange }
                margin="normal"
                label="Cities"
                fullWidth
                value={ values.city_id }
              />
            )}
          />

          <Button
            variant="contained"
            color="primary"
            type="submit"
          >
            Submit
          </Button>
        </Form>
      )}
    </Formik>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Edit angry-goldstine-8offj

3 个答案:

答案 0 :(得分:3)

您的问题是handleChange无法按照您的方式工作。

如果您看看handleChange docs

  

常规输入更改事件处理程序。这将更新values [key],其中key是发出事件的输入的name属性。如果不存在name属性,则handleChange将查找输入的id属性。注意:“输入”在这里表示所有HTML输入。

应该可以正常工作,但问题是TextField中的Autocomplete仅在您键入内容时会触发handleChange,并且值将是文本,而不是id或其他所需属性,因此您需要将handleChange移至Autocomplete

还有一个问题,您不能在handleChange中使用Autocomplete,因为它没有引用您想要的输入,并且它的参数与普通的onChange不同docs中可以看到input中的一个。

  

onChange
  func
  值更改时触发回调。
    签名:
    function(event: object, value: any) => void
    event:回调的事件源
    value:null

所以您需要做的是使用setFieldValue并将其像

一样传递给Autocomplete
onChange={(e, value) => setFieldValue("city_id", value)}

您需要传递字段名称和想要获取的值。

这里是working example

答案 1 :(得分:2)

@vencovsky提供了正确的答案,该答案仍适用于Material UI 14.10.1。

由于要在使用required验证的情况下将字段设置为Yup,因此要添加更多内容。

要使其正常工作,我需要执行以下操作: Yup配置:

validationSchema = {
    Yup.object().shape({
        contact: Yup.string().max(255).required('Contact is required'),
    })
}

反应:

<Autocomplete
    id="contact-autocomplete"
    options={contacts}
    getOptionLabel={(contact) => `${contact?.firstName} ${contact?.lastName}`}
    onChange={(e, value) => setFieldValue("contact", value?.id || "")}
    onOpen={handleBlur}
    includeInputInList
    renderInput={(params) => (
        <TextField
            {...params}
            error={Boolean(touched.contact && errors.contact)}
            fullWidth
            helperText={touched.contact && errors.contact}
            label="Contact Person"
            name="contact"
            variant="outlined"
        />
    )}
/>

当用户单击Autocomplete元素时,它会触发onOpen并运行Formik onBlur并将该字段标记为已触摸。如果没有选择项目,则在Formik flags字段中显示Contact is required验证消息。

答案 2 :(得分:0)

您必须在onChange = {(event, value) => handleChange(value)}标签中将Autocomplete添加为

import React from "react";
import ReactDOM from "react-dom";
import { Formik, Form } from 'formik';
import TextField from '@material-ui/core/TextField';
import Autocomplete from '@material-ui/lab/Autocomplete';
import Button from '@material-ui/core/Button';

import { cities } from '../data/cities';

import "./styles.css";

const [cityId,setCityId]=React.useState({city_id:''});

const handleChange=(value)=>{
  // Here is the value is a selected option label or the new typed value
  setCityId({city_id:value});
}


function App() {
  return (
     <Formik
      initialValues={ cityId }
      onSubmit={() => {
        alert(`Value for city_id is: ${cityId.city_id}`);
      }}
    >
      {({
        handleChange,
        values,
      }) => (
        <Form>
          <Autocomplete
            id="city_id"
            name="city_id"
            options={ cities }
            groupBy={ option => option.state }
            getOptionLabel={ option => option.name }
            style={{ width: 300 }}
            onChange = {(event, value) => handleChange(value)}
            renderInput={params => (
              <TextField
                { ...params }
                onChange={ handleChange }
                margin="normal"
                label="Cities"
                fullWidth
                value={ values.city_id }
              />
            )}
          />

          <Button
            variant="contained"
            color="primary"
            type="submit"
          >
            Submit
          </Button>
        </Form>
      )}
    </Formik>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

如果onChange不起作用,您也可以使用onInputChange。