【问题标题】:Always Display Default Option with React Material-UI Autocomplete使用 React Material-UI 自动完成始终显示默认选项
【发布时间】:2021-11-17 08:36:57
【问题描述】:

我在 React 中使用 Material-UI Autocomplete 进行地址搜索/验证表单,并且我希望始终有一个默认选项,无论结果如何。

在 Angular 中,我使用 [displayWith] 和一个函数来告诉它始终显示具有特定 ID 的数组中的项目,但我不确定如何在 React 中执行此操作。我一直试图找出filterOptions,但我不希望它根据与输入相关的任何内容进行过滤,我只是希望它始终是一个选项。

在这个简化的示例中,如果我希望它始终显示带有年份的电影:1111,我该怎么做?

import React, { useState, ChangeEvent } from 'react';
import {
  TextField,
  InputAdornment
} from "@material-ui/core";
import Autocomplete from '@material-ui/lab/Autocomplete';
import { Search } from "@material-ui/icons";
import axios from "axios";

const AddressSearch = (props) => {

  const [addressesList, setAddressesList] = useState([]);
  const [inputAddress, setInputAddress] = useState<string>("");

  const handleAddressChange = (event: ChangeEvent<{ value: unknown }>) => {
    setInputAddress(event.target.value as string);
  };

  const topFilms = [
    { title: 'I HATE MOVIES', year: 1111 },
    { title: 'The Shawshank Redemption', year: 1994 },
    { title: 'The Godfather'},
    { title: 'The Godfather: Part II', year: 1974 }
  ]

  return (
    <div>
      <Autocomplete
        id="address-autocomplete"
        freeSolo
        options={topFilms}
        getOptionLabel={(option) => option.title}
        popupIcon={<Search />}
        renderInput={(params) => <TextField 
          id="address-input"                          
          {...params} 
          onChange={handleAddressChange}
          placeholder="Quickly find your address" 
          InputProps={{ ...params.InputProps,
          startAdornment: (
            <InputAdornment position="start"><Search /></InputAdornment>
          )}}
        /> }
      />
    </div>
  );
}

export default AddressSearch;

注意:我正在使用的网站使用的是 Material-UI v 4.12

【问题讨论】:

    标签: javascript reactjs autocomplete material-ui


    【解决方案1】:

    您可以创建filterOptions 的包装器,而无需触及原始filterOptions 中的任何内容。只需像往常一样过滤,获取结果,看看是否有默认选项,如果没有,请重新添加:

    import TextField from "@mui/material/TextField";
    import Autocomplete, { createFilterOptions } from "@mui/material/Autocomplete";
    
    const _filterOptions = createFilterOptions();
    const filterOptions = (options, state) => {
      const results = _filterOptions(options, state);
    
      if (!results.includes(myDefaultOption)) {
        results.unshift(myDefaultOption);
      }
    
      return results;
    };
    
    export default function ComboBox() {
      return (
        <Autocomplete
          filterOptions={filterOptions}
          options={options}
          sx={{ width: 300 }}
          renderInput={(params) => <TextField {...params} label="Movie" />}
        />
      );
    }
    
    const myDefaultOption = { label: "My default option", year: 1994 };
    
    const options = [
      myDefaultOption,
      ...
    ]
    

    现场演示

    【讨论】:

      【解决方案2】:

      编辑:根据您的评论,您想从源中获取固定值,因此我进行了一些更改。

      编辑:添加您的年份:1111 示例。

      CodeSandbox

      ...

      您可以将 filterOptions Docs 添加到 Autocomplete 元素,然后将 固定值 添加到结果中。

      过滤选项和来源: Link to documentation

      const filterOptions = createFilterOptions({
        ignoreCase: true,
        ignoreAccents: true
      })
      
      const topFilms = [
        { title: 'Elysium', year: 2013 },
        { title: 'I HATE MOVIES', year: 1111 },
        { title: 'The Shawshank Redemption', year: 1994 },
        { title: 'The Godfather' },
        { title: 'The Godfather: Part II', year: 1974 }
      ]
      

      addressesList 状态存储您要修复的值的标题,我从您的代码中获取了这个钩子

      const [addressesList, setAddressesList] = useState([1111])
      

      从源中取出固定值,因此它们不会重复,此过滤器只会触发一次,或者如果源或“addressesList”发生变化。

      const fixedValues = useMemo(() => topFilms.filter(e => addressesList.includes(e.year)), [topFilms, addressesList])
      const dynamicValues = useMemo(() => topFilms.filter(e => !addressesList.includes(e.year)), [topFilms, addressesList])
      

      自动完成组件的变化。

      <Autocomplete
         filterOptions={(options, _ref) => [...fixedValues, ...filterOptions(options, _ref)]}
         ...Other attributes
      />
      

      最终代码:

      import React, { useState, ChangeEvent, useMemo } from 'react'
      import { TextField, InputAdornment } from "@material-ui/core"
      import Autocomplete, { createFilterOptions } from '@material-ui/lab/Autocomplete'
      import { Search } from "@material-ui/icons"
      
      const filterOptions = createFilterOptions({
        ignoreCase: true,
        ignoreAccents: true
      })
      
      const topFilms = [
        { title: 'Elysium', year: 2013 },
        { title: 'I HATE MOVIES', year: 1111 },
        { title: 'The Shawshank Redemption', year: 1994 },
        { title: 'The Godfather' },
        { title: 'The Godfather: Part II', year: 1974 }
      ]
      
      const AddressSearch = (props) => {
      
        const [addressesList, setAddressesList] = useState([1111])
        const [inputAddress, setInputAddress] = useState("")
      
        const handleAddressChange = (event) => {
          setInputAddress(event.target.value)
        }
      
        const fixedValues = useMemo(() => topFilms.filter(e => addressesList.includes(e.year)), [topFilms, addressesList])
        const dynamicValues = useMemo(() => topFilms.filter(e => !addressesList.includes(e.year)), [topFilms, addressesList])
      
        return (
          <div>
            <Autocomplete
              id="address-autocomplete"
              freeSolo
              options={dynamicValues}
              getOptionLabel={(option) => option.title}
              popupIcon={<Search />}
              filterOptions={(options, _ref) => [...fixedValues, ...filterOptions(options, _ref)]}
              renderInput={(params) => <TextField
                id="address-input"
                {...params}
                onChange={handleAddressChange}
                placeholder="Quickly find your address"
                InputProps={{
                  ...params.InputProps,
                  startAdornment: (
                    <InputAdornment position="start"><Search /></InputAdornment>
                  )
                }}
              />}
            />
          </div>
        )
      }
      
      export default AddressSearch
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-05
        • 2021-11-12
        • 2020-08-07
        • 2017-05-19
        • 2020-04-16
        • 2018-04-27
        • 2020-04-16
        • 2022-01-09
        相关资源
        最近更新 更多