跳到主要內容
+

自動完成

自動完成元件是一個文字輸入框,透過建議選項面板來增強功能。

簡介

自動完成元件是一個增強型的文字輸入框,會在使用者輸入時顯示建議選項列表,並讓使用者從列表中選取選項。

MUI Base 提供了 useAutocomplete Hook,用於建構自訂的自動完成功能。 它實作了 WAI-ARIA Combobox 模式,通常用於協助使用者更快地完成表單輸入或搜尋查詢。

Hook

import { useAutocomplete } from '@mui/base/useAutocomplete';

useAutocomplete Hook 需要一個 options 列表,以便在文字框獲得焦點時顯示。 該值必須從預定義的值集中選擇。

以下示範展示如何建立一個簡單的下拉式方塊、套用樣式,以及使用 onChange 屬性將選取的值寫入狀態變數

按下 Enter 鍵開始編輯

自訂

渲染選項

預設情況下,options 屬性接受 string{ label: string } 的陣列

const options = [
  { label: 'The Godfather', id: 1 },
  { label: 'Pulp Fiction', id: 2 },
];
// or
const options = ['The Godfather', 'Pulp Fiction'];

如果您需要為選項使用不同的結構,則必須為 getOptionLabel 屬性提供一個函式,將每個選項解析為唯一值。

const options = [
  { issuer: 'Bank of America', brand: 'Visa', last4: '1234' },
  { issuer: 'Bank of America', brand: 'MasterCard', last4: '5678' },
  { issuer: 'Barclays', brand: 'Visa', last4: '4698' },
  // ...
];

const {
  getRootProps,
  // etc
} = useAutocomplete({
  getOptionLabel: (option) => option.last4,
});

受控狀態

useAutocomplete Hook 有兩種可以控制的狀態

  1. 使用 value/onChange 屬性組合的「value」狀態。 此狀態表示使用者選取的值,例如按下 Enter 鍵時。
  2. 使用 inputValue/onInputChange 屬性組合的「input value」狀態。 此狀態表示文字框中顯示的值。

這兩個狀態是隔離的,應獨立控制。

value: Firefox
inputValue: 

使用 Portal

React Portal 可用於在 DOM 階層之外渲染列表框,使其更容易「浮動」在相鄰元素之上。

MUI Base 提供了圍繞 React 的 createPortal() 建構的 Popper 元件,正是為了這個目的,並且還可以協助您管理鍵盤焦點,因為它會在 Portal 內外移動。

若要在 MUI Base 的 Popper 中渲染列表框,ref 必須按如下方式合併

import { useAutocomplete } from '@mui/base/useAutocomplete';
import { Popper } from '@mui/base/Popper';
import { unstable_useForkRef as useForkRef } from '@mui/utils';

export default function App(props) {
  const {
    getRootProps,
    getInputProps,
    getListboxProps,
    getOptionProps,
    popupOpen,
    anchorEl,
    setAnchorEl,
    groupedOptions,
  } = useAutocomplete(props);

  const rootRef = useForkRef(ref, setAnchorEl);

  return (
    <React.Fragment>
      <div {...getRootProps()} ref={rootRef}>
        <input {...getInputProps()} />
      </div>
      {anchorEl && (
        <Popper open={popupOpen} anchorEl={anchorEl}>
          {groupedOptions.length > 0 && (
            <ul {...getListboxProps()}>
              {groupedOptions.map((option, index) => (
                <li {...getOptionProps({ option, index })}>{option.label}</li>
              ))}
            </ul>
          )}
        </Popper>
      )}
    </React.Fragment>
  );
}

這是一個完整的示範,展示如何在 Popper 內渲染列表框