인프런/스프링 MVC 2편

5)타임리프 - 라디오버튼,셀렉트박스

backend dev 2023. 2. 2.

라디오버튼

라디오 버튼은 여러 선택지 중에 하나를 선택할 때 사용할 수 있다.

이번시간에는 라디오 버튼을 자바 ENUM을 활용해서 개발해보자.

목표

 

@ModelAttribute를 이용해서 컨트롤러의 모든 메소드의

모델에 값을 넣자

@ModelAttribute("itemTypes")
public ItemType[] itemTypes() {
    return ItemType.values(); // // enum.values를 하면 저장되어있는 값들을 배열로 넘겨준다.
}

enum타입은 .values()로 값들을 가져올 수 있따.

 

<!-- radio button -->
<div>
    <div>상품 종류</div>
    <div th:each="type : ${itemTypes}" class="form-check form-check-inline">
        <input type="radio" th:field="*{itemType}" th:value="${type.name()}"
               class="form-check-input">
        <label th:for="${#ids.prev('itemType')}" th:text="${type.description}"
               class="form-check-label">
            BOOK
        </label>
    </div>
</div>

itemTypes 데이터로 받아온 enum배열을 하나씩 type에 저장한다.

th:field에 Item.itemType을 넣는다. 

th:value에는 type.name()을 이용해서 enum값에서 이름을 가져온다. (BOOK,FOOD,ETC가 이름임)

소스보기 결과

상품등록을 해보면

다음과 같이 쿼리스트링이 날아가는것을 확인할 수 있다.

로그로 item객체의 itemType에는 어떻게 저장되는지 확인!

 

 

만약 라디어버튼 체크를 안하면?

값이 안날아간다!
그러므로 null이 저장되어있따.

해결방법

1. item이라는 데이터를 보낼때 ItemType을 지정해서 보낸다.

@GetMapping("/add")
public String addForm(Model model) {
    Item item = new Item();
    item.setItemType(ItemType.BOOK);
    model.addAttribute("item",item); 
    
    return "form/addForm";
}

 

 

그렇게하면 기본값을 설정해둘수있다.

 

2. 하지만 비워져있게 냅두고 만약 사용자가 체크를 안했을시 메시지창을 띄우는식이 더 사용자에게 좋을거같다는 의견이있다. 왜냐면 라디오버튼을 체크했다고 착각하고 넘어갈수도있기때문이다!

 

 

타임리프에서 ENUM 직접 접근하기

@ModelAttribute("itemTypes")
public ItemType[] itemTypes() {
    return ItemType.values(); // // enum.values를 하면 저장되어있는 값들을 배열로 넘겨준다.
}

이런식으로 Enum을 직접 모델에 담아서 전달하는 대신에 타임리프는 자바객체에 직접 접근할 수 있다.

<div th:each="type : ${T(hello.itemservice.domain.item.ItemType).values()}" class="form-check form-check-inline">

하지만 비추천!


셀렉트 박스

셀렉트 박스는 여러 선택지 중에 하나를 선택할 때 사용할 수 있다. 

 

이번시간에는 셀렉트 박스를 자바 객체를 활용해서 개발해보자.

 

누르면 선택지가 보이는 셀렉트박스를 만들어보자.

 

 

@ModelAttribute("deliveryCodes")
public List<DeliveryCode> deliveryCodes() {
    List<DeliveryCode> deliveryCodes = new ArrayList<>();
    deliveryCodes.add(new DeliveryCode("FAST","빠른배송"));
    deliveryCodes.add(new DeliveryCode("NORMAL","일반배송"));
    deliveryCodes.add(new DeliveryCode("SLOW","느린배송"));
    return deliveryCodes;
}

이전 과같이 @ModelAttribute를 이용해서 모든 메소드의 모델에 데이터를 넣어주자. (공용으로 쓰이는것은 이렇게하는게 코드의 중복도 없앨수 있다.)

그래서 다른곳에 미리 생성해두고, 불러와서 쓰는것이 더 효율적이다!

 

셀렉트박스 코드

<!-- SELECT -->
<div>
    <div>배송 방식</div>
    <select th:field="*{deliveryCode}" class="form-select">
        <option value="">==배송 방식 선택==</option>
        <option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}"
                th:text="${deliveryCode.displayName}">FAST</option>
    </select>
</div>

셀렉트박스 소스보기

등록했을때 쿼리스트링

<select th:field="*{deliveryCode}" class="form-select">

th:field로 인해 생성되는 id를 파라미터명으로 사용

<option value="">==배송 방식 선택==</option>

기본선택은 value를 ""로 해서 기본선택으로 냅두고 제출하면 빈값이 넘어오게끔

<option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}"
        th:text="${deliveryCode.displayName}">FAST</option>

데이터로 넘겨온 deliveryCodes를 하나씩 받아 deliveryCode로 넣고, value는 코드값(FAST,SLOW,NORMAL)

text는 이름값(빠른배송,일반배송,느린배송)을 넣는것을 반복한다.

 

결과!

 

 

타임리프가 selected를 넣는 방법

<!-- SELECT -->
<div>
    <div>배송 방식</div>
    <select th:field="*{deliveryCode}" class="form-select">
        <option value="">==배송 방식 선택==</option>
        <option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}"
                th:text="${deliveryCode.displayName}">FAST</option>
    </select>
</div>

th:field로 현재 아이템이 선택한 deliveryCode를 가져왔다.

 

그리고

<option th:each="deliveryCode : ${deliveryCodes}" th:value="${deliveryCode.code}"

th:each를 돌면서 데이터로 들어온 deliveryCode들을 하나씩 th:field로 들어온 현재 아이템이 선택한 deliveryCode와 비교해서 code값이 같다면 그 <option> 태그에 selected 속성을 추가해준다.

 

 

 

댓글