Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

MATERIAL-UIのMultiple SelectでChipから選択を解除する

$
0
0

はじめに

React + Typescript + MaterialUIでフロントエンドを作成していたときに実現したいことができなかったので参考程度に投稿します。

実現できなかった原因

Chipの×ボタンを押してもSelectのメニューが出てきてしまう

実現したいこと

MaterialUIの公式ドキュメントに書かれていた「Multiple Select(Chip)」でChipの×ボタンからも選択を解除したい!
last.gif

結論

Chipコンポーネントに以下プロパティを追加

onMouseDown={(event)=>{event.stopPropagation();}}

前提条件

  • typescript,React,MaterialUiについてある程度の知識がある。
  • create-react-appでアプリケーションが作成済み
npx create-react-app {your_app_name} --template typescript
npm install @material-ui/core

Multiple SelectのChipを動かしてみる

まずは何も考えずコードをすべてコピーしてApp.tsxに貼り付ける。
次にChip以外のところは邪魔なのでChipに関連するものだけを残す。
そうするとコードは以下のようになります。

App.tsx
importReactfrom'react';import{createStyles,makeStyles,useTheme,Theme}from'@material-ui/core/styles';importInputfrom'@material-ui/core/Input';importInputLabelfrom'@material-ui/core/InputLabel';importMenuItemfrom'@material-ui/core/MenuItem';importFormControlfrom'@material-ui/core/FormControl';importSelectfrom'@material-ui/core/Select';importChipfrom'@material-ui/core/Chip';constuseStyles=makeStyles((theme:Theme)=>createStyles({formControl:{margin:theme.spacing(1),minWidth:120,maxWidth:300,},chips:{display:'flex',flexWrap:'wrap',},chip:{margin:2,},noLabel:{marginTop:theme.spacing(3),},}),);constITEM_HEIGHT=48;constITEM_PADDING_TOP=8;constMenuProps={PaperProps:{style:{maxHeight:ITEM_HEIGHT*4.5+ITEM_PADDING_TOP,width:250,},},};constnames=['Oliver Hansen','Van Henry','April Tucker','Ralph Hubbard','Omar Alexander','Carlos Abbott','Miriam Wagner','Bradley Wilkerson','Virginia Andrews','Kelly Snyder',];functiongetStyles(name:string,personName:string[],theme:Theme){return{fontWeight:personName.indexOf(name)===-1?theme.typography.fontWeightRegular:theme.typography.fontWeightMedium,};}exportdefaultfunctionMultipleSelect(){constclasses=useStyles();consttheme=useTheme();const[personName,setPersonName]=React.useState<string[]>([]);consthandleChange=(event:React.ChangeEvent<{value:unknown}>)=>{setPersonName(event.target.valueasstring[]);};return(<div><FormControlclassName={classes.formControl}><InputLabelid="demo-mutiple-chip-label">Chip</InputLabel><SelectlabelId="demo-mutiple-chip-label"id="demo-mutiple-chip"multiplevalue={personName}onChange={handleChange}input={<Inputid="select-multiple-chip"/>}renderValue={(selected)=>(<divclassName={classes.chips}>{(selectedasstring[]).map((value)=>(<Chipkey={value}label={value}className={classes.chip}/>))}</div>)}MenuProps={MenuProps}>{names.map((name)=>(<MenuItemkey={name}value={name}style={getStyles(name,personName,theme)}>{name}</MenuItem>))}</Select></FormControl></div>);}

そしてこれをnpm startしてhttp://localhost:3000でみると
first.gif
よさそう!※拡大してます

Chipの×ボタンを表示する

Chipに×ボタンを表示するにはChipコンポーネントにonDeleteプロパティを追加すればいい。

Apptsx
<Chipkey={value}label={value}className={classes.chip}onDelete={()=>{alert(value)}}/> #ここを追

今回は×ボタンをがクリックされたことを確認するために、alertでクリックしたChipのラベルを表示するようにした。
そして再度npm start
second.gif

あれ...?何度押しても×ボタンがクリックできずにSelectのメニューが出てきてしまう。

対処法

Chipコンポーネントに以下プロパティを追加

App.tsx
<Chipkey={value}label={value}className={classes.chip}onDelete={()=>{alert(value)}}onMouseDown={(event)=>{event.stopPropagation()}}#ここを追加/>

そして再度npm start
third.gif

今度はきちんとクリックされてアラートが出ていますね。

Chip削除の処理を追加する

先ほど入れたalertの処理をChip削除(personName内の名前を削除)する処理に変える。

新しくchipDeleteという関数を用意する

 const chipDelete = (name: string) => {
    setPersonName(personName.filter(value => value !== name))
  }

そうするとApp.tsxfunction MultipleSelect()は以下のようになる

App.tsx
exportdefaultfunctionMultipleSelect(){constclasses=useStyles();consttheme=useTheme();const[personName,setPersonName]=React.useState<string[]>([]);consthandleChange=(event:React.ChangeEvent<{value:unknown}>)=>{setPersonName(event.target.valueasstring[]);};constchipDelete=(name:string)=>{setPersonName(personName.filter(value=>value!==name))};return(<div><FormControlclassName={classes.formControl}><InputLabelid="demo-mutiple-chip-label">Chip</InputLabel><SelectlabelId="demo-mutiple-chip-label"id="demo-mutiple-chip"multiplevalue={personName}onChange={handleChange}input={<Inputid="select-multiple-chip"/>}renderValue={(selected)=>(<divclassName={classes.chips}>{(selectedasstring[]).map((value)=>(<Chipkey={value}label={value}className={classes.chip}onDelete={(event)=>chipDelete(value)}onMouseDown={(event)=>{event.stopPropagation();}}/>))}</div>)}MenuProps={MenuProps}>{names.map((name)=>(<MenuItemkey={name}value={name}style={getStyles(name,personName,theme)}>{name}</MenuItem>))}</Select></FormControl></div>);}

そしてnpm start
last.gif

うまくいった!!!!:v:

終わりに

今思うとこんなにすっとできてしまうなんて。。。
ただ単にコピペするだけではなくてどのような処理が行われていて、どんなオプションのプロパティがあるのかを確認しないといけないですね。


Viewing all articles
Browse latest Browse all 8691

Trending Articles