如何根据所选数据自动填充其他自动完成值,并在数据尚不存在时添加数据?

How do I autofill the other autocomplete values based on the selected data and also add the data if it does not exist yet?

如何匹配名字和姓氏,然后让它自动填充其他自动完成字段?可能存在多个相似的名字或姓氏但地址不同的情况。另外,如果数据中不存在名字、姓氏和地址,请添加。

到目前为止,我无法匹配名字和姓氏。但是,如果用户不存在,我可以添加并在控制台中查看他们的名字、姓氏和地址。

重新创建代码和框:https://codesandbox.io/s/freesolocreateoption-demo-material-ui-forked-oclo3s?file=/demo.js

代码:

export default function FreeSoloCreateOption() {
  const [firstName, setFirstName] = useState("");
  const [lastName, setLastName] = useState("");
  const [streetAddress, setStreetAddress] = useState("");

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(firstName, "firstName");
    console.log(lastName, "firstName");
    console.log(streetAddress, "street address");
  };
  return (
    <form onSubmit={handleSubmit}>
      <Autocomplete
        required
        value={firstName}
        onChange={(event, newValue) => {
          if (typeof newValue === "string") {
            setFirstName(newValue);
          } else if (newValue && newValue.inputValue) {
            // Create a new value from the user input
            setFirstName(newValue.inputValue);
          } else {
            setFirstName(newValue);
          }
        }}
        filterOptions={(options, params) => {
          const filtered = filter(options, params);

          const { inputValue } = params;
          // Suggest the creation of a new value
          const isExisting = options.some(
            (option) => inputValue === option.firstName
          );
          if (inputValue !== "" && !isExisting) {
            filtered.push({
              inputValue,
              firstName: `Add "${inputValue}"`
            });
          }

          return filtered;
        }}
        selectOnFocus
        clearOnBlur
        handleHomeEndKeys
        id="free-solo-with-text-demo"
        options={data}
        getOptionLabel={(option) => {
          // Value selected with enter, right from the input
          if (typeof option === "string") {
            return option;
          }
          // Add "xxx" option created dynamically
          if (option.inputValue) {
            return option.inputValue;
          }
          // Regular option
          return option.firstName;
        }}
        renderOption={(props, option) => <li {...props}>{option.firstName}</li>}
        sx={{ width: 300 }}
        freeSolo
        renderInput={(params) => <TextField {...params} label="First Name" />}
      />
      <br />

      <Autocomplete
        value={lastName}
        onChange={(event, newValue) => {
          if (typeof newValue === "string") {
            setLastName(newValue);
          } else if (newValue && newValue.inputValue) {
            // Create a new value from the user input
            setLastName(newValue.inputValue);
          } else {
            setLastName(newValue);
          }
        }}
        filterOptions={(options, params) => {
          const filtered = filter(options, params);

          const { inputValue } = params;
          // Suggest the creation of a new value
          const isExisting = options.some(
            (option) => inputValue === option.lastName
          );
          if (inputValue !== "" && !isExisting) {
            filtered.push({
              inputValue,
              lastName: `Add "${inputValue}"`
            });
          }

          return filtered;
        }}
        selectOnFocus
        clearOnBlur
        handleHomeEndKeys
        id="free-solo-with-text-demo"
        options={data}
        getOptionLabel={(option) => {
          // Value selected with enter, right from the input
          if (typeof option === "string") {
            return option;
          }
          // Add "xxx" option created dynamically
          if (option.inputValue) {
            return option.inputValue;
          }
          // Regular option
          return option.lastName;
        }}
        renderOption={(props, option) => <li {...props}>{option.lastName}</li>}
        sx={{ width: 300 }}
        freeSolo
        renderInput={(params) => <TextField {...params} label="Last Name" />}
        required
      />

      <br />
      <Autocomplete
        value={streetAddress}
        onChange={(event, newValue) => {
          if (typeof newValue === "string") {
            setStreetAddress(newValue);
          } else if (newValue && newValue.inputValue) {
            // Create a new value from the user input
            setStreetAddress(newValue.inputValue);
          } else {
            setStreetAddress(newValue);
          }
        }}
        filterOptions={(options, params) => {
          const filtered = filter(options, params);

          const { inputValue } = params;
          // Suggest the creation of a new value
          const isExisting = options.some(
            (option) => inputValue === option.streetAddress
          );
          if (inputValue !== "" && !isExisting) {
            filtered.push({
              inputValue,
              streetAddress: `Add "${inputValue}"`
            });
          }

          return filtered;
        }}
        selectOnFocus
        clearOnBlur
        handleHomeEndKeys
        id="free-solo-with-text-demo"
        options={data}
        getOptionLabel={(option) => {
          // Value selected with enter, right from the input
          if (typeof option === "string") {
            return option;
          }
          // Add "xxx" option created dynamically
          if (option.inputValue) {
            return option.inputValue;
          }
          // Regular option
          return option.streetAddress;
        }}
        renderOption={(props, option) => (
          <li {...props}>{option.streetAddress}</li>
        )}
        sx={{ width: 300 }}
        freeSolo
        renderInput={(params) => (
          <TextField {...params} label="Street Address" />
        )}
        required
      />
      <Button type="submit">submit</Button>
    </form>
  );
}

// Top 100 films as rated by IMDb users. http://www.imdb.com/chart/top
const data = [
  {
    streetAddress: "Street Address 1",
    firstName: "Alex",
    lastName: "Dhan"
  },
  {
    streetAddress: "Street Address 2",
    firstName: "Alex",
    lastName: "Dhan"
  },
  {
    streetAddress: "Street Address 3",
    firstName: "Alex",
    lastName: "Last name"
  },
  {
    streetAddress: "Street Address 4",
    firstName: "Jin",
    lastName: "Iu"
  },
  {
    streetAddress: "Street Address 5",
    firstName: "Po",
    lastName: "Yie"
  }
];
 

如果我没看错,您想将新数据添加到自动完成,Mui 示例不会向选项数组显示附加值。您必须使用本地状态或 API:

将数据保存在选项数组中
import * as React from 'react'
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete'
import { TextField } from '../TextField/TextField'

const filter = createFilterOptions<string>()

const trimCreatedValue = (addedValue: string | null) => {
  if (typeof addedValue !== 'string') return ''

  // extract actual word between " e.g. added option "
  const _o = addedValue.match(/"(.*?)"/)

  // Add "xxx" option created dynamically
  if (_o) {
    return _o[1]
  }
  return addedValue
}

export const SelectCreate: React.FC<IPropsSelectCreate> = ({ items, onChange }) => {
  const [value, setValue] = React.useState<string | null>(null)

  return (
    <Autocomplete
      value={value}
      onChange={(_event, newValue: string | null) => {
        setValue(trimCreatedValue(newValue))
        onChange(trimCreatedValue(newValue))
      }}
      filterOptions={(options: string[], params) => {
        const filtered = filter(options, params)

        const { inputValue } = params
        // Suggest the creation of a new value
        const isExisting = options.some(option => inputValue === option)
        if (inputValue !== '' && !isExisting) {
          filtered.push(`Add "${inputValue}"`)
        }

        return filtered
      }}
      options={items}
      getOptionLabel={trimCreatedValue}
      renderOption={(props, option) => <li {...props}>{option}</li>}
      freeSolo
      renderInput={params => <TextField {...params} />}
    />
  )
}

export interface IPropsSelectCreate {
  items: string[]
  onChange: (val: string | null) => void
}

您需要一个助手来根据您为选项定义的内容过滤选项(firstNamelastNamestreetAddress)。它可能是这样的:

function filterData(allData, { firstName, lastName }) {
  const filteredData = allData.filter((dt) => {
    const first =
      typeof firstName === "string" ? firstName : firstName?.firstName;
    const last = typeof lastName === "string" ? lastName : lastName?.lastName;

    return (
      (!first || first === dt.firstName) && (!last || last === dt.lastName)
    );
  });

  // TODO: This line enables you to select from list data if nothing left!
  // Remove it and just return filteredData if you want filter works normally :)
  return filteredData.length ? filteredData : allData;
}

这可以帮助您:

  1. 过滤选项,
  2. 并且,设置值

下一个根据您当前选择的内容自动完成。

查看 this code on Codesandbox 了解其工作原理。

关注代码中的 TODO 标签以获取有关可用选项的更多数据。