React + Material-UI で次のような感じのタグフォームを作るのに、
必要なオプション指定の仕方がすぐに分からなかったので簡単にメモ。
※公式ドキュメントはこちら
React Autocomplete component - Material-UI
https://material-ui.com/ja/components/autocomplete/#creatable
Autocomplete API - Material-UI
https://material-ui.com/ja/api/autocomplete/#main-content
前提
"@material-ui/core": "^4.11.2",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.57",
"react": "^16.13.1",
必要なオプション
Autocomplete Componentに
- multiple ・・複数可にする
- freeSolo ・・自由入力可にする
- clearOnBlur ・・新規選択肢を追加可にする
-
onChange={(e,v) => setTags(v)}
・・入力値をuseStateを使ってセットする- ※追記2020/12/20: こちらのonChangeは 不要でした
TexstField Componentに
{(e) => {setTags(e.target.value)}}
・・入力値をuseStateを使ってセットする-
{(e,v) => setTags(v.map(tag=>tag.title ? tag.title : tag))}
・・入力値をuseStateを使ってセットする- ※追記2020/12/20: enterキーで入力した時に取得できる値が異なったので修正しました
コード全体
import { useState } from "react";
import AddIcon from '@material-ui/icons/Add';
import Autocomplete, { createFilterOptions } from '@material-ui/lab/Autocomplete';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import IconButton from '@material-ui/core/IconButton';
import TextField from '@material-ui/core/TextField';
const filter = createFilterOptions();
export default function TaskCreateForm(props) {
const [tags, setTags] = useState([]);
const [addFormOpen, setAddFormOpen] = useState(false);
const handleClickAddFormOpen = () => {
setAddFormOpen(true);
};
const handleAddFormClose = () => {
setAddFormOpen(false);
};
const add = () => {
setTags([]);
console.log(tags);
handleAddFormClose();
}
return (
<div>
<IconButton aria-label="add" color="primary" onClick={handleClickAddFormOpen}>
<AddIcon />
</IconButton>
<Dialog open={addFormOpen} onClose={handleAddFormClose} aria-labelledby="form-dialog-title">
<DialogContent style={{ minWidth: 400 }}>
<form className={classes.formRoot} noValidate autoComplete="off">
<div>
<Autocomplete
id="tags"
size="small"
options={[]}
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.title;
}}
multiple // 複数可
freeSolo // 自由入力可
clearOnBlur // 新規選択肢を追加可
filterOptions={(options, params) => {
const filtered = filter(options, params);
// Suggest the creation of a new value
if (params.inputValue !== '') {
filtered.push({
inputValue: params.inputValue,
title: params.inputValue,
});
}
return filtered;
}}
onChange={(e,v) => setTags(v.map(tag=>tag.title ? tag.title : tag))}
//★ ←複数のテキストを取得するにはココ必要(※追記修正2020/12/20)
renderInput={(params) => (
<TextField
{...params}
label="tag"
variant="standard"
// onChange={(e) => {setTags(e.target.value)}} //★ ←ココは消してOK(※追記2020/12/20)
/>
)}
/>
</div>
</form>
</DialogContent>
<DialogActions>
<Button onClick={handleAddFormClose} color="primary">
Cancel
</Button>
<Button onClick={add} color="primary" variant="contained">
Add
</Button>
</DialogActions>
</Dialog>
</div>
);
}
参考
マテリアルUIからのオートコンプリートコンポーネントの変更の処理
https://qastack.jp/programming/58684579/handle-change-on-autocomplete-component-from-material-ui