6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

React + Material-UI でタグのような複数指定できるフォームを作るには

Last updated at Posted at 2020-12-15

React + Material-UI で次のような感じのタグフォームを作るのに、
必要なオプション指定の仕方がすぐに分からなかったので簡単にメモ。

react-material-ui-tags.png

※公式ドキュメントはこちら

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

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?