Gmail メール作成のアドレス表示のように、入力・選択した文字をタグ表示する方法です。React UIライブラリのMUIで作れると知り試作。共有したい方がいたので、この機会に調べた内容を残すことにしました。ご使用の際は、少しでも調査の時短につながれば嬉しいです。
試作品
離島名をタグ表示しました。
GitHub: rito-marker
環境
typescript: 4.9.5
react: 18.2.0
react-dom: 18.2.0
mui: 5.11.7
mui v5を使用するには次のバージョンが必要です
react: 17.0.0 以上
react-dom: 17.0.0 以上
公式情報
Peer dependencies
react >= 17.0.0 and react-dom >= 17.0.0 are peer dependencies.
方法
- MUIをインストール
- Autocompleteコンポーネントを使用
- タグのカラーを変更
1. MUIをインストール
npm install @mui/material @emotion/react @emotion/styled
yarn add @mui/material @emotion/react @emotion/styled
2. Autocompleteコンポーネント
Autocompleteのデモ を参考にしました。必要なコンポーネントをインポートし、次のようにreturnします。
import { Autocomplete, TextField } from '@mui/material' //必要なコンポーネントをインポート
// ~~ 省略 ~~
return (
// ~~ 省略 ~~
<Autocomplete //importしたコンポーネントを使用
multiple //複数選択できるようになる --- ①
freeSolo //任意の入力値を管理できる(デフォルトはオプション選択のみ)
filterSelectedOptions //選択されたオプションを非表示にする --- ②
options={islands.map(option => option.name)} //ドロップダウンメニューの項目:文字列の配列
value={inputValues} //入力欄に表示される値:①のときは文字列の配列、指定しないときは文字列 --- ③
onChange={handleInputChange} //コールバック関数(オプションを選択か「Enter」を押すとイベントが起きる): function --- ④
sx={{
width: 600,
display: 'inline-block',
}}
renderInput={params => (
<TextField //importしたコンポーネント
{...params}
variant='standard'
label='離島マーカーを作る' // --- ⑤
placeholder='離島名を選択か、入力後に「Enter」でタグが表示。「+」でマーカーを作成'
error={validation.error} //エラー状態(trueのときは⑤labelや⑥helperTextが赤色になる): boolean
helperText={validation.message} //入力欄の下に表示されるテキスト: node(公式のデモ通り文字列を指定) // --- ⑥
/>
)}
/>
)
②の補足
選択されたオプションは非表示になります。
ですが、選択後に「+」ボタンでマーカーを作るようにしたので、その場合は再レンダー時にoptionsの配列で初期化され表示されます。そのため、マーカーを作成した離島は取り除きoptionsに含まないようにしました。
// Inputのセレクトオプション。textsにある離島名は削除し表示しない
const islands = useMemo(
() => ISLANDS.filter(island => texts.indexOf(island.name) === -1),
[texts]
)
④の補足
コールバック関数(handleInputChange)が受け取る主な引数は、function(event, value) です。なので入力した値はevent.target.value
ではなくvalue
で渡されます。また、multipleのときは文字列の配列で、指定しないときは文字列になります。このvalueを③のvalueへセットする流れになります。
3. タグのカラーを変更
今回はカラーを変更しませんでしたが、追加で調べました。2. AutocompleteデモのCodeSandboxを参考にrenderTags
を追加します。図のようにChipコンポーネントを加え、例えばcolor='info'
で画像のようにinfoカラーになります。今回はスタイル変更ではなくcolorを指定する簡単な例まででした。
import { Autocomplete, TextField, Chip } from '@mui/material' //Chipを追加
// ~~ 省略 ~~
<Autocomplete
// ~~ 省略 ~~
renderTags={(value: readonly string[], getTagProps) =>
value.map((option: string, index: number) => (
<Chip variant='outlined' label={option} color='info' {...getTagProps({ index })} /> //選択した離島名が各optionに渡される
))
}
// ~~ 省略 ~~
/>
面白い名前の島があるんですね。ちなみに村役場さんの公式サイトを見ると、宝島は「海とサンゴと伝説に彩られたロマンの島」のようです