Material ui Autocomplete:可以在“Enter”事件之外的事件上创建标签吗?

IT技术 javascript reactjs material-ui
2021-04-12 07:42:07

我目前正在使用 freesolo Autocomplete,我的特定用例需要在输入文本后面有逗号或空格时创建标签。自动完成目前在 Enter 事件上创建标签,但我认为 Autocomplete 中没有任何内置功能支持在任何其他事件上创建标签。我想知道我是否遗漏了什么,或者如果我没有遗漏,我该如何解决这个问题?

目前,我正在尝试使用 Autocomplete 中的 onInputChange 属性来捕获传入的字符串。我检查该字符串中的逗号和空格,并在成功找到其中一个字符后,使用一些本机 JS 手动触发 Enter 事件代码。这在某些情况下有效,但并非在所有情况下都有效,并且考虑所有情况变得乏味。这种方法似乎容易出现很多问题,我不相信这是在不同事件上实现标签创建的最佳方式。寻找一些想法。谢谢

onInputChange 属性用法:

<Autocomplete
        multiple
        freeSolo
        filterSelectedOptions
        id="auto-complete"
        options={foo.map(bar => bar.name)}
        ref={autoRef}
        onInputChange={(e, value) => {
            createTagOnEvent(value);
        }}/>

在输入中搜索逗号和空格并手动触发 Enter 事件:

const createTagOnEvent = (bar) => {
    if (pattern.test(bar)) {
        const ke = new KeyboardEvent("keydown", {bubbles: true, cancelable: true, keyCode: 13});
        autoRef.current.dispatchEvent(ke);
    }
};
2个回答

下面是我推荐的方法。

该方法有两个主要方面:

  1. 使用“受控”输入方法,Autocomplete以便您可以完全控制当前值。

  2. 使用适当的逻辑为输入指定onKeyDown处理程序以添加新值。TextFieldparams.inputProps.onKeyDown

import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";

export default function Tags() {
  const [value, setValue] = React.useState([top100Films[13]]);
  const handleKeyDown = event => {
    switch (event.key) {
      case ",":
      case " ": {
        event.preventDefault();
        event.stopPropagation();
        if (event.target.value.length > 0) {
          setValue([...value, event.target.value]);
        }
        break;
      }
      default:
    }
  };
  return (
    <div style={{ width: 500 }}>
      <Autocomplete
        multiple
        freeSolo
        id="tags-outlined"
        options={top100Films}
        getOptionLabel={option => option.title || option}
        value={value}
        onChange={(event, newValue) => setValue(newValue)}
        filterSelectedOptions
        renderInput={params => {
          params.inputProps.onKeyDown = handleKeyDown;
          return (
            <TextField
              {...params}
              variant="outlined"
              label="filterSelectedOptions"
              placeholder="Favorites"
              margin="normal"
              fullWidth
            />
          );
        }}
      />
    </div>
  );
}

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films = [
  { title: "The Shawshank Redemption", year: 1994 },
  { title: "The Godfather", year: 1972 },
// ... many more options
];

编辑自动完成按键覆盖

这是一个typescript版本:

/* eslint-disable no-use-before-define */
import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete, { RenderInputParams } from "@material-ui/lab/Autocomplete";

interface ObjectOption {
  title: string;
  year: number;
}
type Option = ObjectOption | string;

interface MyInputProps {
  onKeyDown: (event: object) => void;
}
interface MyParams extends RenderInputParams {
  inputProps: MyInputProps;
}

export default function Tags() {
  const [value, setValue] = React.useState([top100Films[13]]);
  const handleKeyDown = event => {
    switch (event.key) {
      case ",":
      case " ": {
        event.preventDefault();
        event.stopPropagation();
        if (event.target.value.length > 0) {
          setValue([...value, event.target.value]);
        }
        break;
      }
      default:
    }
  };
  return (
    <div style={{ width: 500 }}>
      <Autocomplete
        multiple
        freeSolo
        id="tags-outlined"
        options={top100Films}
        getOptionLabel={option => {
          if (typeof option === "string") {
            return option;
          }
          return option.title;
        }}
        value={value}
        onChange={(event, newValue) => setValue(newValue)}
        filterSelectedOptions
        renderInput={(params: MyParams) => {
          params.inputProps.onKeyDown = handleKeyDown;
          return (
            <TextField
              {...params}
              variant="outlined"
              label="filterSelectedOptions"
              placeholder="Favorites"
              margin="normal"
              fullWidth
            />
          );
        }}
      />
    </div>
  );
}

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const top100Films: ObjectOption[] = [
  { title: "The Shawshank Redemption", year: 1994 },
  { title: "The Godfather", year: 1972 },
// ... many more options
];

编辑 Typescript 自动完成覆盖 keydown

@Sammy 我今天开始学习 Typescript,所以我添加了一个 Typescript 版本。
2021-05-31 07:42:07
您好,不幸的是,上面的方法不起作用,至少使用 Typescript,因为event.target.value它不存在。
2021-06-01 07:42:07
@Sammy 抱歉,但我个人不使用 Typescript,因此我无法提供有关如何向其中添加适当类型的建议。
2021-06-02 07:42:07
谢谢瑞安!你也可以看看我在这里做了什么:codesandbox.io/s/wild-sea-h2i0m
2021-06-03 07:42:07

正如这里回答的,只需使用autoHighlight标志:

<Autocomplete autoHighlight {...} />

默认情况下,它会突出显示第一个选项,因此按 Enter 键将选中它。