【问题标题】:Capturing Tab Key on Material UI AutoComplete Component在 Material UI 自动完成组件上捕获 Tab 键
【发布时间】:2020-05-26 12:20:27
【问题描述】:

这是一个沙盒:https://codesandbox.io/s/wild-sea-h2i0m

这是该沙盒中自动完成的代码:

import React from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import Chip from "@material-ui/core/Chip";
import CloseIcon from "@material-ui/icons/Close";
import TextField from "@material-ui/core/TextField";
import { FieldProps } from "formik";

const isEmailValid = (email: string) =>
  /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);

const EmailsField = ({
  field,
  form: { errors, touched, setTouched, setFieldValue },
  ...props
}: FieldProps) => {
  const name = field.name;
  const [value, setValue] = React.useState<string[]>([]);
  const [inputValue, setInputValue] = React.useState("");

  const handleChange = (event: React.ChangeEvent<{}>, emails: string[]) => {
    setTouched({ ...touched, [name]: true });
    setValue(emails);
    event.persist();
    setFieldValue(name, emails);
  };

  const handleInputChange = (
    event: React.ChangeEvent<{}>,
    newInputValue: string
  ) => {
    const options = newInputValue.split(/[ ,]+/);
    const fieldValue = value
      .concat(options)
      .map(x => x.trim())
      .filter(x => x);

    if (options.length > 1) {
      handleChange(event, fieldValue);
    } else {
      setInputValue(newInputValue);
    }
  };

  return (
    <Autocomplete<string>
      multiple
      disableClearable={true}
      options={[]}
      freeSolo
      renderTags={(emails, getTagProps) =>
        emails.map((email, index) => (
          <Chip
            deleteIcon={<CloseIcon />}
            variant="default"
            label={email}
            color={isEmailValid(email) ? "primary" : "secondary"}
            {...getTagProps({ index })}
          />
        ))
      }
      value={value}
      inputValue={inputValue}
      onChange={handleChange}
      onInputChange={handleInputChange}
      renderInput={params => (
        <TextField
          {...params}
          name={name}
          error={touched[name] && Boolean(errors.emails)}
          helperText={touched[name] && errors.emails}
          variant="outlined"
          InputProps={{ ...params.InputProps }}
          {...props}
        />
      )}
    />
  );
};

export default EmailsField;

在用户键入然后按 Tab 键盘按钮移动到提交按钮后,我无法使用户键入的值成为单个选项。

知道怎么做吗?

【问题讨论】:

  • 您有多个自动完成。如果您在不使用 Enter 的情况下使用 Tab,您是否要创建一个新选项,因为除非您这样做,否则自动完成保留该值是没有意义的
  • 升级到最新版@material-ui/core@material-ui/labcodesandbox.io/s/autocomplete-vtozu
  • 没错,这就是我想要的!
  • @RyanCogswell 谢谢你,但这并没有改变,还是我错过了什么?
  • Tab 不再导致值在升级后消失。

标签: reactjs material-ui


【解决方案1】:

您可以通过为onKeyDown 添加处理程序来完成此操作:

  const handleKeyDown = (event: React.KeyboardEvent) => {
    switch (event.key) {
      case "Tab": {
        if (inputValue.length > 0) {
          handleChange(event, value.concat([inputValue]));
        }
        break;
      }
      default:
    }
  };

然后通过inputProps将其添加到文本输入中:

      renderInput={params => {
        params.inputProps.onKeyDown = handleKeyDown;
        return (
          <TextField
            {...params}
            name={name}
            error={touched[name] && Boolean(errors.emails)}
            helperText={touched[name] && errors.emails}
            variant="outlined"
            {...props}
          />
        );
      }}

这是您沙盒中 EmailsField 组件的完整新代码:

import React from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import Chip from "@material-ui/core/Chip";
import CloseIcon from "@material-ui/icons/Close";
import TextField from "@material-ui/core/TextField";
import { FieldProps } from "formik";

const isEmailValid = (email: string) =>
  /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);

const EmailsField = ({
  field,
  form: { errors, touched, setTouched, setFieldValue },
  ...props
}: FieldProps) => {
  const name = field.name;
  const [value, setValue] = React.useState<string[]>([]);
  const [inputValue, setInputValue] = React.useState("");

  const handleChange = (event: React.ChangeEvent<{}>, emails: string[]) => {
    setTouched({ ...touched, [name]: true });
    setValue(emails);
    event.persist();
    setFieldValue(name, emails);
  };

  const handleInputChange = (
    event: React.ChangeEvent<{}>,
    newInputValue: string
  ) => {
    const options = newInputValue.split(/[ ,]+/);
    const fieldValue = value
      .concat(options)
      .map(x => x.trim())
      .filter(x => x);

    if (options.length > 1) {
      handleChange(event, fieldValue);
    } else {
      setInputValue(newInputValue);
    }
  };

  const handleKeyDown = (event: React.KeyboardEvent) => {
    switch (event.key) {
      case "Tab": {
        if (inputValue.length > 0) {
          handleChange(event, value.concat([inputValue]));
        }
        break;
      }
      default:
    }
  };
  return (
    <Autocomplete<string>
      multiple
      disableClearable={true}
      options={[]}
      freeSolo
      renderTags={(emails, getTagProps) =>
        emails.map((email, index) => (
          <Chip
            deleteIcon={<CloseIcon />}
            variant="default"
            label={email}
            color={isEmailValid(email) ? "primary" : "secondary"}
            {...getTagProps({ index })}
          />
        ))
      }
      value={value}
      inputValue={inputValue}
      onChange={handleChange}
      onInputChange={handleInputChange}
      renderInput={params => {
        params.inputProps.onKeyDown = handleKeyDown;
        return (
          <TextField
            {...params}
            name={name}
            error={touched[name] && Boolean(errors.emails)}
            helperText={touched[name] && errors.emails}
            variant="outlined"
            {...props}
          />
        );
      }}
    />
  );
};

export default EmailsField;

相关回答:Material ui Autocomplete: can tags be created on events aside from 'Enter' events?

【讨论】:

    猜你喜欢
    • 2020-09-23
    • 1970-01-01
    • 2016-08-06
    • 2013-10-26
    • 2023-03-24
    • 1970-01-01
    • 2020-07-30
    • 1970-01-01
    • 2015-12-06
    相关资源
    最近更新 更多