質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

0回答

2808閲覧

[React] 動的なTableにおけるセレクトボックスで選択済みの選択肢を消したい

Reiz

総合スコア29

Material-UI

Material-UIは、Material Designを利用可能なオープンソースのReact向けUIコンポーネントキットです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2020/11/20 09:56

やりたいこと

行を追加したり削除する動的なテーブルでセレクトボックスの選択肢を一度使ったら別の行では使えないようにしたい

使っているライブラリなど

行の追加、削除のテーブル部分はFormikというライブラリを使って実装しています。

イメージ説明

試行錯誤

セレクトボックスを選択したら配列のpopで配列から消すロジックを考えましたが、実装できませんでした。
「Apple」と「Rice」は画面描画時に自動的に選んでおきたいので、initialValuesで初期値として設定しています。
セレクトボックスの選択肢から省けば良いかと思いましたが、省くと描画時に選択できません。

ソースコード

jsx

1import React from "react"; 2import { Formik, Form, FieldArray } from "formik"; 3 4// Material UI 5import { makeStyles } from "@material-ui/core/styles"; 6...(省略) 7import * as yup from "yup"; 8 9const useStyles = makeStyles((theme) => ({ 10 header: { 11...(省略) 12})); 13 14const validationSchema = yup.object().shape({ 15 data: yup.array().of( 16 yup.object().shape({ 17 code: yup.object().typeError("Please select a code"), 18 free: yup.string().required("Please select free option"), 19 additionalPrice: yup.string().required("Please enter additional price") 20 }) 21 ) 22}); 23 24const codes = [ 25 { id: 1, name: "Banana", desc: "Desc 1", price: 100 }, 26 { id: 2, name: "Grape", desc: "Desc 2", price: 200 }, 27 { id: 3, name: "Orange", desc: "Desc 3", price: 300 }, 28 { id: 4, name: "Apple", desc: "Required", price: 500 }, 29 { id: 5, name: "Rice", desc: "Required", price: 500 } 30]; 31const foodOptions = ["Banana", "Grape", "Orange", "Apple", "Rice"]; 32const freeOptions = ["Yes", "No"]; 33 34const initialValues = { 35 data: [ 36 { 37 code: "Apple", 38 free: "No", 39 additionalPrice: 0 40 }, 41 { 42 code: "Rice", 43 free: "No", 44 additionalPrice: 0 45 } 46 ] 47}; 48 49const Reports = () => { 50 const classes = useStyles(); 51 52 return ( 53 <div> 54 <Grid container direction="row"> 55 <Grid item lg={12} md={12} xs={12}> 56 <Card> 57 <CardHeader 58 className={classes.header} 59 title={"Report"} 60 classes={{ 61 title: classes.header 62 }} 63 /> 64 <Divider /> 65 <CardContent> 66 <Formik 67 initialValues={initialValues} 68 onSubmit={(values) => { 69 console.log(values.data); 70 }} 71 validationSchema={validationSchema} 72 > 73 {({ 74 values, 75 handleChange, 76 setFieldValue, 77 errors, 78 handleBlur, 79 touched 80 }) => { 81 return ( 82 <Form> 83 <FieldArray name="data"> 84 {({ insert, remove, push }) => ( 85 <Paper> 86 <TableContainer> 87 <Table stickyHeader> 88 <TableHead> 89 <TableRow> 90 <TableCell>Code - (Description)</TableCell> 91 <TableCell>Free</TableCell> 92 <TableCell>Price</TableCell> 93 <TableCell>Additional Price</TableCell> 94 <TableCell>Actions</TableCell> 95 </TableRow> 96 </TableHead> 97 <TableBody> 98 {values.data.map((record, idx) => { 99 return ( 100 <TableRow key={idx} hover> 101 <TableCell> 102 <Select 103 onBlur={handleBlur} 104 labelId="demo-simple-select-outlined-label" 105 label="Foods" 106 name={`data.${idx}.code`} 107 onChange={handleChange} 108 value={ 109 values.data[idx] && 110 values.data[idx].code 111 ? values.data[idx].code 112 : "" 113 } 114 > 115 {foodOptions.map((item) => ( 116 <MenuItem key={item} value={item}> 117 {item} 118 </MenuItem> 119 ))} 120 </Select> 121 </TableCell> 122 <TableCell> 123 <FormControl 124 variant="outlined" 125 className={classes.formControl} 126 error={Boolean( 127 touched.data && 128 touched.data[idx] && 129 touched.data[idx].free && 130 errors.data && 131 errors.data[idx] && 132 errors.data[idx].free 133 )} 134 > 135 <InputLabel id="demo-simple-select-outlined-label"> 136 Free 137 </InputLabel> 138 <Select 139 onBlur={handleBlur} 140 labelId="demo-simple-select-outlined-label" 141 label="Free" 142 name={`data.${idx}.free`} 143 onChange={handleChange} 144 value={ 145 values.data[idx] && 146 values.data[idx].free 147 ? values.data[idx].free 148 : "" 149 } 150 > 151 {freeOptions.map((item) => ( 152 <MenuItem 153 key={item} 154 value={item} 155 > 156 {item} 157 </MenuItem> 158 ))} 159 </Select> 160 {touched.data && 161 touched.data[idx] && 162 touched.data[idx].free && 163 errors.data && 164 errors.data[idx] && 165 errors.data[idx].free ? ( 166 <FormHelperText> 167 {errors.data[idx].free} 168 </FormHelperText> 169 ) : null} 170 </FormControl> 171 </TableCell> 172 <TableCell> 173 {values.data[idx] && 174 values.data[idx].code 175 ? values.data[idx].code.price 176 : 0} 177 </TableCell> 178 <TableCell> 179 <TextField 180 label="Additional Price" 181 type="number" 182 variant="outlined" 183 placeholder="0" 184 name={`data.${idx}.additionalPrice`} 185 value={ 186 values.data[idx] && 187 values.data[idx].additionalPrice 188 } 189 onChange={handleChange} 190 onBlur={handleBlur} 191 error={Boolean( 192 touched.data && 193 touched.data[idx] && 194 touched.data[idx] 195 .additionalPrice && 196 errors.data && 197 errors.data[idx] && 198 errors.data[idx].additionalPrice 199 )} 200 helperText={ 201 touched.data && 202 touched.data[idx] && 203 touched.data[idx] 204 .additionalPrice && 205 errors.data && 206 errors.data[idx] && 207 errors.data[idx].additionalPrice 208 ? errors.data[idx] 209 .additionalPrice 210 : "" 211 } 212 /> 213 </TableCell> 214 <TableCell> 215 <Button 216 variant="contained" 217 color="secondary" 218 onClick={() => { 219 remove(idx); 220 }} 221 > 222 Remove 223 </Button> 224 </TableCell> 225 </TableRow> 226 ); 227 })} 228 <TableRow> 229 <TableCell>Total</TableCell> 230 <TableCell></TableCell> 231 <TableCell></TableCell> 232 <TableCell></TableCell> 233 <TableCell> 234 {values.data.reduce((total, curVal) => { 235 if (!curVal.code) { 236 return total; 237 } 238 if (curVal.free === "Yes") { 239 return total; 240 } 241 return ( 242 total + 243 curVal.code.price + 244 (curVal.additionalPrice || 0) 245 ); 246 }, 0)} 247 </TableCell> 248 </TableRow> 249 </TableBody> 250 </Table> 251 </TableContainer> 252 <Box> 253 <Button 254 variant="contained" 255 color="primary" 256 onClick={() => 257 push({ 258 code: null, 259 free: "No", 260 additionalPrice: 0 261 }) 262 } 263 > 264 Add Row 265 </Button> 266 </Box> 267 <Box display="flex" flexDirection="row-reverse"> 268 <Button 269 variant="contained" 270 color="primary" 271 type="submit" 272 > 273 Save 274 </Button> 275 </Box> 276 </Paper> 277 )} 278 </FieldArray> 279 </Form> 280 ); 281 }} 282 </Formik> 283 </CardContent> 284 </Card> 285 </Grid> 286 </Grid> 287 </div> 288 ); 289}; 290 291export default Reports; 292

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問