概要
MUIのAutocompleteでは、入力したテキストはリストが選択されない場合は、フォーカスを外れると入力内容がクリアされます。テキストを残したい場合に、ドキュメントではfreeSolo
の設定が紹介されてますがこの設定は個人的に課題を感じ、別の実装方法があるか調べてみたのでそのメモ書きです。
前提
- 使用した
mui/material
のバージョンは6.3.1です。
freeSoloに個人的に感じた課題
-
[Autocomplete] freeSolo prop makes onChange value type become T | stringの記事にある通り、
onChange
に入る型にstringが混じります。実際は選択時はoptionで選択した型が入るのですが、上記のバージョンの時点では型判定をしなければいけない状況です。 - Autocompleteのデフォルトでは、optionから選択後にクリアボタンが表示されます。しかしfreeSoloを設定すると、optionから未選択のテキスト入力時にも表示されます。クリアボタンを押したらテキストがクリアされるだけなのですが、optionから選択されたものかどうかが一見して分からないというふうにも感じてしまいます。
他の実装方法案
stateで入力されたテキストを管理し、inputValue
にそのstateを設定することでテキストを残すことができます。
この実装では型にstringが混じることはないし、テキストを入力しただけではクリアボタンが表示されません。
実装サンプル
上記の実装案で実装したサンプルは、以下になります。
export const AutoCompleteSample: FC = () => {
// AutoCompleteの選択内容(型は公式ドキュメントの内容と同様)
const [selectValue, setSelectValue] = useState<FilmOptionType | null>(null);
// テキストの入力内容
const [textValue, setTextValue] = useState<string | null>(null);
return (
<>
<Autocomplete
options={top100Films} // top100Filmsの内容は公式ドキュメントの内容と同様
value={selectValue}
getOptionLabel={(option) => {
if (typeof option === "string") {
return option;
}
return option.title;
}}
onChange={(_, newValue) => {
setSelectValue(newValue);
setTextValue(newValue?.title ?? "");
}}
inputValue={textValue ?? ""}
renderInput={(params) => (
<TextField
{...params}
label="Search input"
onChange={(event) => {
setTextValue(event.target.value);
}}
/>
)}
/>
<div>
<div>textValue:{textValue}</div>
<div>selectValue:{selectValue?.title}</div>
</div>
</>
);
};