autoFocus 自动完成问题 Material UI

Problem autoFocus Autocomplete Material UI

我无法 focus 我表单的第一个元素,它是 Material UI.

的自动完成组件

打开模态框时,焦点在'unit'元素上,如下图: It dont's work

我想让焦点在'group'元素上,如下图: It work

这里是沙盒 link: https://codesandbox.io/s/awesome-bassi-zjp50?file=/src/MyForm.jsx:1422-1431

谁能帮帮我?

我的表格

import React from "react";
import { Formik, Form, Field } from "formik";
import * as Yup from "yup";
import { Grid } from "@material-ui/core";
import Input from "./components/Input";
import Autocomplete from "./components/Autocomplete";

const initialValues = {
  id: 0,
  group: {
    value: 0,
    label: ""
  },
  name: "",
  unit: {
    value: 0,
    label: ""
  }
};

const groupList = [
  {
    value: "1",
    label: "Seeds"
  },
  {
    value: "2",
    label: "Fertilizers"
  }
];

const unitList = [
  {
    value: "1",
    label: "kg"
  },
  {
    value: "2",
    label: "t"
  }
];

const validationSchema = Yup.object({
  group: Yup.object().shape({
    value: Yup.number().required().min(1).nullable()
  }),
  name: Yup.string().required().max(50),
  unit: Yup.object().shape({
    value: Yup.number().required().min(1).nullable()
  })
});

export default function MyForm() {
  function _onSubmit(fields, { props, setErrors, setSubmitting }) {
    console.log(fields);
  }

  return (
    <Formik
      enableReinitialize={true}
      initialValues={initialValues}
      validationSchema={validationSchema}
      onSubmit={_onSubmit}
    >
      {function Render({ errors, touched, isSubmitting, setFieldValue }) {
        return (
          <Form id="form">
            <Grid container direction="row">
              <Grid item xs={12}>
                <Field
                  name="group"
                  autoFocus
                  component={Autocomplete}
                  label="Group"
                  options={groupList}
                  disabled={isSubmitting}
                  textFieldProps={{
                    fullWidth: true,
                    margin: "dense",
                    variant: "outlined"
                  }}
                />
              </Grid>
              <Grid item xs={12}>
                <Field
                  name="name"
                  fullWidth
                  label="Name"
                  disabled={isSubmitting}
                  component={Input}
                />
              </Grid>
              <Grid item xs={12}>
                <Field
                  name="unit"
                  component={Autocomplete}
                  label="Unit"
                  options={unitList}
                  disabled={isSubmitting}
                  textFieldProps={{
                    fullWidth: true,
                    margin: "dense",
                    variant: "outlined"
                  }}
                />
              </Grid>
            </Grid>
          </Form>
        );
      }}
    </Formik>
  );
}

弹出模式

import React from "react";
import {
  Dialog,
  DialogTitle,
  DialogContent,
  makeStyles,
  Typography,
  Divider,
  DialogActions,
  Button,
  Grid,
  Box
} from "@material-ui/core";

const useStyles = makeStyles((theme) => ({
  dialogWrapper: {
    padding: theme.spacing(2),
    position: "absolute",
    top: theme.spacing(5)
  },
  dialogTitle: {
    paddingRight: 0
  },
  button: {
    margin: theme.spacing(0.5),
    textTransform: "none"
  },
  buttonsContainer: {
    display: "flex",
    flex: "0 0 auto",
    justifyContent: "flex-end",
    width: "100%",
    height: "100%"
  },
  buttons: {
    display: "flex"
  },
  loadingIcon: {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    marginRight: theme.spacing(1)
  }
}));

function Popup(props) {
  const classes = useStyles();
  const { title, children, openPopup, setOpenPopup, ...rest } = props;

  return (
    <Dialog
      {...rest}
      open={openPopup}
      maxWidth="sm"
      classes={{ paper: classes.dialogWrapper }}
    >
      <DialogTitle dividers="true" className={classes.dialogTitle}>
        <div style={{ display: "flex" }}>
          <Typography variant="h4" component="div" style={{ flexGrow: 1 }}>
            {title}
          </Typography>
        </div>
      </DialogTitle>
      <Divider />
      <DialogContent {...rest} direction="row">
        {children}
      </DialogContent>
      <DialogActions {...rest}>
        <Grid {...rest} container className={classes.buttonsContainer}>
          <Box {...rest} className={classes.buttons}>
            <Button
              className={classes.button}
              variant="contained"
              color="primary"
              type="submit"
              form="form"
              {...rest}
            >
              Save
            </Button>
            <Button
              className={classes.button}
              color="default"
              fullWidth
              onClick={() => {
                setOpenPopup(false);
              }}
              {...rest}
            >
              Cancel
            </Button>
          </Box>
        </Grid>
      </DialogActions>
    </Dialog>
  );
}

export default Popup;

自动完成

import React from "react";
import { FieldProps, getIn } from "formik";
import { TextField, CircularProgress } from "@material-ui/core";
import MuiAutocomplete, {
  createFilterOptions
} from "@material-ui/lab/Autocomplete";

const NewAutocomplete: React.FC<
  FieldProps & {
    label?: string,
    options: Array<{ label: string, value: number }>
  }
> = ({ textFieldProps, field, form, label, options, isLoading, ...props }) => {
  const filterOptions = createFilterOptions({
    matchFrom: "start",
    limit: 500
  });
  const errorText =
    getIn(form.touched, field.name) && getIn(form.errors, field.name);

  const valueInit = [
    {
      value: 0,
      label: ""
    }
  ];

  return (
    <MuiAutocomplete
      {...props}
      {...field}
      filterOptions={filterOptions}
      options={[...valueInit, ...options]}
      getOptionLabel={(option) => (option ? option.label : "")}
      getOptionSelected={(option, value) => option.value === value?.value}
      style={{ width: 300 }}
      loading={isLoading}
      value={field.value}
      onChange={(e, value) => {
        form.setFieldValue(field.name, value);
      }}
      renderInput={(props) => (
        <>
          <TextField
            {...props}
            {...textFieldProps}
            label={label}
            helperText={errorText?.value || errorText}
            error={!!errorText}
            autoFocus
            InputProps={{
              ...props.InputProps,
              endAdornment: (
                <React.Fragment>
                  {isLoading ? (
                    <CircularProgress color="primary" size={20} />
                  ) : null}
                  {props.InputProps.endAdornment}
                </React.Fragment>
              )
            }}
          />
        </>
      )}
    />
  );
};

export default NewAutocomplete;

感谢您的帮助!

您实际上在 TextField 上默认将 autoFocus 设置为 true 在您的 NewAutocomplete 定义中(src/components/Autocomplete.jsx:50 在您的沙箱中).

删除该行后,您可以将 autoFocus: true 添加到 MyForm 组件中第一个 FieldtextFieldProps 值。

codesandbox example