내 아들은 효자인가 #6 - Input 조작2
저번에 예고했던 대로~
다른 컴포넌트에게 영향을 주는 이벤트들을 해보도록 하자~
< select >
이 부분
지금 보는 것과 같이 유닛과 아이돌이 따로 놀고 있는 것을 볼 수 있다.
유닛을 선택했을 때 소속 아이돌만 나오도록 바꿔보도록 하겠다~!
아이돌이 너무너무 많기 때문에... 일단은 유성대와 발키리로만 조작했다가 나중에 디비 연결하게 되면 넣어보도록 하자!
데이터를 어떻게 들여오면 좋을지 interface를 먼저 정의해보고, 그에 맞게 데이터를 설정했다.
// select item interface
interface SelectVal {
value: string;
name: string;
}
// 삭제 예정 =============
const allIdol: SelectVal[] = [
{ value: "모리사와 치아키", name: "모리사와 치아키" },
{ value: "신카이 카나타", name: "신카이 카나타" },
{ value: "나구모 테토라", name: "나구모 테토라" },
{ value: "센고쿠 시노부", name: "센고쿠 시노부" },
{ value: "타카미네 미도리", name: "타카미네 미도리" },
{ value: "이츠키 슈", name: "이츠키 슈" },
{ value: "카게히라 미카", name: "카게히라 미카" },
];
const ryuseitai: SelectVal[] = [
{ value: "모리사와 치아키", name: "모리사와 치아키" },
{ value: "신카이 카나타", name: "신카이 카나타" },
{ value: "나구모 테토라", name: "나구모 테토라" },
{ value: "센고쿠 시노부", name: "센고쿠 시노부" },
{ value: "타카미네 미도리", name: "타카미네 미도리" },
];
const valkyrie: SelectVal[] = [
{ value: "이츠키 슈", name: "이츠키 슈" },
{ value: "카게히라 미카", name: "카게히라 미카" },
];
// //삭제 예정 =============
그리고 아이돌 선택 부분의 목록이 계속 변경될 것이기 때문에 그 부분을 따로 state로 선언했다.
// select 목록
const [selectIdol, setSelectIdol] = useState<SelectVal[]>(allIdol);
대분류의 초기값이 전체이기 때문에 소분류도 그에 맞게 전체 목록을 불러오도록 하였다.
이제 대분류가 변경될 때마다 목록이 바뀌어야 하기 때문에, 대분류가 바뀔 때(onChange) 소분류의 목록을 가져오도록 코드를 추가해준다.
<Select
labelId="selectUnitLabel"
id="selectUnit"
label="Unit"
value={unit}
onChange={(event: SelectChangeEvent<string>) => {
setUnit(event.target.value);
setIdol("");
switch (event.target.value) {
case "유성대":
setSelectIdol(ryuseitai);
break;
case "발키리":
setSelectIdol(valkyrie);
break;
default:
setSelectIdol(allIdol);
}
}}
>
<MenuItem value="all">all</MenuItem>
<MenuItem value="유성대">유성대</MenuItem>
<MenuItem value="발키리">발키리</MenuItem>
</Select>
그럼 해당 set에 따라 소분류 다시 목록을 그리도록 마저 수정해준다.
<Select
labelId="selectIdolLabel"
id="selectIdol"
label="Idol"
value={idol}
onChange={(event: SelectChangeEvent<string>) => {
setIdol(event.target.value);
}}
>
{selectIdol.map((option: SelectVal, index: number) => (
<MenuItem key={"idolItem" + index} value={option.value}>
{option.name}
</MenuItem>
))}
</Select>
(map을 이용하여 <MenuItem> 컴포넌트를 그릴 때 경고 메시지가 나와 key를 추가하였다.)
(https://sheep-h.tistory.com/15)
< Radio >
다음은 이 부분을 조작해볼 것이다.
앙스타를 한스타, 일스타를 둘 다 해보면 알겠지만 한스타에는 스카우트 티켓이 있고, 일스타에는 없다.
때문에 한스타를 선택했을 시에만 사용 스카우트 티켓을 입력할 수 있는 부분을 노출하도록 만들겠다.
이번엔 state를 따로 선언하지 않고, 기존에 있던 cate state를 활용해본다.
- radio click event
한스타 클릭 시 노출, 일스타 클릭시 비노출 & 티켓 개수 초기화
<RadioGroup
row
aria-labelledby="cate-radio-buttons-group"
name="cate-radio-buttons-group"
value={cate}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setCate(event.target.value);
//다이아 티켓 입력값 초기화
setUseDiaCnt(0);
setUseTicketCnt(0);
setPickCnt(0);
}}
>
<FormControlLabel value="ko" control={<Radio />} label="한스타" />
<FormControlLabel value="jp" control={<Radio />} label="일스타" />
</RadioGroup>
- input 노출 처리
{cate === "ko" && (
<Grid item xs={12}>
<TextField
label="사용 스카우트 티켓"
id="useTicket"
sx={{}}
type="number"
value={useTicketCnt}
InputProps={{
endAdornment: <InputAdornment position="end">개</InputAdornment>,
inputProps: { min: 0, max: 1000000 },
}}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
event.target.value
? setUseTicketCnt(parseInt(event.target.value))
: setUseTicketCnt(0);
}}
/>
</Grid>
)}
수정한 코드 전체를 보면 이런 식이다.
- InputBox.tsx
import {
Grid,
FormControl,
InputLabel,
Select,
MenuItem,
RadioGroup,
Radio,
TextField,
FormControlLabel,
InputAdornment,
Button,
SelectChangeEvent,
} from "@mui/material";
import { useState } from "react";
interface InputBoxProps {}
// select item interface
interface SelectVal {
value: string;
name: string;
}
// 삭제 예정 =============
const allIdol: SelectVal[] = [
{ value: "모리사와 치아키", name: "모리사와 치아키" },
{ value: "신카이 카나타", name: "신카이 카나타" },
{ value: "나구모 테토라", name: "나구모 테토라" },
{ value: "센고쿠 시노부", name: "센고쿠 시노부" },
{ value: "타카미네 미도리", name: "타카미네 미도리" },
{ value: "이츠키 슈", name: "이츠키 슈" },
{ value: "카게히라 미카", name: "카게히라 미카" },
];
const ryuseitai: SelectVal[] = [
{ value: "모리사와 치아키", name: "모리사와 치아키" },
{ value: "신카이 카나타", name: "신카이 카나타" },
{ value: "나구모 테토라", name: "나구모 테토라" },
{ value: "센고쿠 시노부", name: "센고쿠 시노부" },
{ value: "타카미네 미도리", name: "타카미네 미도리" },
];
const valkyrie: SelectVal[] = [
{ value: "이츠키 슈", name: "이츠키 슈" },
{ value: "카게히라 미카", name: "카게히라 미카" },
];
// //삭제 예정 =============
const InputBox: React.FC<InputBoxProps> = () => {
//select
const [unit, setUnit] = useState<string>("all");
const [idol, setIdol] = useState<string>("");
// select 목록
const [selectIdol, setSelectIdol] = useState<SelectVal[]>(allIdol);
//radio
const [cate, setCate] = useState<string>("ko");
//text
const [useDiaCnt, setUseDiaCnt] = useState<number>(0);
const [useTicketCnt, setUseTicketCnt] = useState<number>(0);
const [pickCnt, setPickCnt] = useState<number>(0);
return (
<Grid container spacing={3}>
<Grid item xs={6}>
<FormControl fullWidth>
<InputLabel id="selectUnitLabel">유닛</InputLabel>
<Select
labelId="selectUnitLabel"
id="selectUnit"
label="Unit"
value={unit}
onChange={(event: SelectChangeEvent<string>) => {
setUnit(event.target.value);
setIdol("");
switch (event.target.value) {
case "유성대":
setSelectIdol(ryuseitai);
break;
case "발키리":
setSelectIdol(valkyrie);
break;
default:
setSelectIdol(allIdol);
}
}}
>
<MenuItem value="all">all</MenuItem>
<MenuItem value="유성대">유성대</MenuItem>
<MenuItem value="발키리">발키리</MenuItem>
</Select>
</FormControl>
</Grid>
<Grid item xs={6}>
<FormControl fullWidth>
<InputLabel id="selectIdolLabel"> 아이돌 </InputLabel>
<Select
labelId="selectIdolLabel"
id="selectIdol"
label="Idol"
value={idol}
onChange={(event: SelectChangeEvent<string>) => {
setIdol(event.target.value);
}}
>
{selectIdol.map((option: SelectVal, index: number) => (
<MenuItem key={"idolItem" + index} value={option.value}>
{option.name}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
<Grid item xs={12}>
<FormControl>
<RadioGroup
row
aria-labelledby="cate-radio-buttons-group"
name="cate-radio-buttons-group"
value={cate}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
setCate(event.target.value);
//다이아 티켓 입력값 초기화
setUseDiaCnt(0);
setUseTicketCnt(0);
setPickCnt(0);
}}
>
<FormControlLabel value="ko" control={<Radio />} label="한스타" />
<FormControlLabel value="jp" control={<Radio />} label="일스타" />
</RadioGroup>
</FormControl>
</Grid>
<Grid item xs={12}>
<TextField
label="사용 다이아"
id="useDia"
sx={{}}
type="number"
value={useDiaCnt}
InputProps={{
endAdornment: <InputAdornment position="end">개</InputAdornment>,
inputProps: { min: 0, max: 1000000 },
}}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
event.target.value
? setUseDiaCnt(parseInt(event.target.value))
: setUseDiaCnt(0);
}}
/>
</Grid>
{cate === "ko" && (
<Grid item xs={12}>
<TextField
label="사용 스카우트 티켓"
id="useTicket"
sx={{}}
type="number"
value={useTicketCnt}
InputProps={{
endAdornment: <InputAdornment position="end">개</InputAdornment>,
inputProps: { min: 0, max: 1000000 },
}}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
event.target.value
? setUseTicketCnt(parseInt(event.target.value))
: setUseTicketCnt(0);
}}
/>
</Grid>
)}
<Grid item xs={12}>
<TextField
label="뽑은 픽업 카드 수"
id="pickCnt"
sx={{}}
type="number"
value={pickCnt}
InputProps={{
endAdornment: <InputAdornment position="end">개</InputAdornment>,
inputProps: { min: 0, max: 1000 },
}}
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
event.target.value
? setPickCnt(parseInt(event.target.value))
: setPickCnt(0);
}}
/>
</Grid>
<Grid item xs={12}>
<Button
variant="outlined"
onClick={() => {
console.log({
unit: unit,
idol: idol,
cate: cate,
useDiaCnt: useDiaCnt,
useTicketCnt: useTicketCnt,
pickCnt: pickCnt,
});
}}
>
확인
</Button>
</Grid>
</Grid>
);
};
export default InputBox;
+) 개수 입력하는 input에서 경고 메시지가 있어서 수정한 부분이 있다.